Oracle Net8 Administrator's Guide Release 8.0 A58230-01 |
Library | Product | Contents | Index

# 11
Net8 Enhancements for Programmers

Net8 includes an application program interface (API) called Net8 OPEN allowing programmers to develop both database and non-database applications. In addition, Net8 contains several new benefits for programmers including UNIX client programming, signal handler and alarm programming, Bequeath Adapter and child process termination.

This chapter contains the following sections:

- Section 11.1, "Net8 OPEN"
- Section 11.2, "UNIX Client Programming"

## 11.1 Net8 OPEN

Net8 includes an application program interface (API) called Net8 OPEN, which enables programmers to:

- develop both database and non-database applications that make use of the Net8 network already deployed in their environment
- deploy an application developed on one machine to another without having to modify their calls to the network interface

Net8 OPEN provides applications a single common interface to all industry standard network protocols.

The relationship of Net8 OPEN to other products is shown in Figure 11-1.

#### Figure 11-1 Net8 OPEN

Using Net8 OPEN, you can solve a number of problems, such as:

- Three-tier connectivity (client/agent/server) - Use any application to communicate with an agent. For example, the agent might be an application server that allows simultaneous connectivity to Oracle and non-Oracle data sources, such as remote information servers.
- Distributed applications - Build distributed applications that can run over an existing Oracle network without the requirements of a database or additional middleware.
- Enhanced clients - Integrate non-SQL information with SQL applications. For example, a process control application can communicate with a non-SQL application such as a sensor.

### 11.1.1 Net8 OPEN API Function Calls

In contrast to a remote procedure call interface, Net8 OPEN provides a byte stream-oriented API that can be used to develop basic applications which send and receive data. Applications developed with Net8 OPEN must ensure that values sent across the network are interpreted correctly at the receiving end.

The Net8 OPEN API consists of five function calls:

- TNSOPEN
- TNSCLOSE
- TNSSEND
- TNSRECV
- TNSCONTROL

##### Table 11-1 Net8 OPEN API Function Call Summary

TNSOPEN |
--- | ---
Description: | Initializes the Net8 OPEN API per-connection handle. This function must be the first Net8 OPEN call that a user makes. Note that tnsopen() does not establish a connection; connections are established by the send and receive calls as needed. If you are writing a client program (which will initiate the connection), "name" contains a service name in the same format as those in a local naming configuration file. If you are writing a server program, "name" should be NULL. Your server program will pick up the connection automatically when you make the first tnsrecv() call to receive data (see the section on tnsrecv).
Synopsis: |
    int tnsopen(handlep, name)
    void **handlep;
    const char *name;
Parameters: |
    handlep (IN/OUT)
- Address to receive Net8 connection handle
    name (IN)
- Service name
Prerequisites: | The handlep parameter must not be NULL
Returns: | Upon successful completion a zero value is returned. Otherwise, a positive Net8 API error is returned.

#####

TNSCLOSE |
--- | ---
Description: | Shuts down the connection. The user must call this function to close the connection and release the handle properly.
Synopsis: |
    int tnsclose(handlep)
    void **handlep;
Parameters: |
    handlep(IN/OUT)
- Address of a pointer to a Net8 connection handle
Prerequisites: | The handlep parameter must not be NULL.
Returns: | Upon successful completion a zero value is returned, and *handlep is set to NULL. Otherwise, a positive Net8 API error number is returned.

#####

TNSSEND |
--- | ---
Description: | Sends data to the Net8 connection handle. In the first call to tnssend() on the client side, the connection is established before any data is sent to the handle. The client application must first call tnssend() after tnsopen() to establish a connection to the server. It is an error if the client application calls tnsrecv() first, or if the server program calls tnssend() first. Note that this also means that the tnssend() call may return errors related to connection establishment - so the first indication you get that, for instance, you have given the incorrect TNS address, is that an error occurs on the first tnssend() call, rather than on the tnsopen() call as you may first expect.
Synopsis: |
    int tnssend(handle, data, length)
    void *handle;
    const void *data;
    size_t *length;
Parameters: |
    handle(IN/OUT) - pointer to Net8 connection
    handle returned by tnsopen()
    data(IN) - pointer to data to be sent
    length(IN/OUT) - pointer to the length of data to
    be sent in bytes and the actual number of bytes
    written on return.
Prerequisites: | The parameters must not be NULL.
Returns: | Upon successful completion a zero value is returned, and the actual number of bytes written is returned as the value pointed to by the length parameter. Otherwise, a positive Net8 API error number is returned.

#####

TNSRECV |
--- | ---
Description: | Receives data from the Net8 connection handle. In the first call to tnsrecv() on the server side, the connection is established before data is received from the handle. The server must first call tnsrecv() after tnsopen() to accept the connection from the client. Incoming connections are accepted by the Net8 Listener (tnslsnr), which automatically spawns off a copy of your server program when needed, and hands it the new connection. You must configure the network listener with the location of your server program for this to occur - see the section on configuration below.
Synopsis: |
    int tnsrecv(handle, data, length)
    void *handle;
    void *data;
    size_t *length;
Parameters: |
    handle(IN/OUT) - pointer to Net8 connection
    handle returned by tnsopen()
    data(IN/OUT) - pointer to buffer to receive data
    length(IN/OUT) - pointer to the length of buffer
    to receive data and actual number of bytes
    received on return
Prerequisites: | All parameters must not be NULL.
Returns: | Upon successful completion a zero value is returned, and the actual number of bytes received is returned as the value pointed to by the length parameter. Otherwise, a positive Net8 API error number is returned.

#####

TNSCONTROL |
--- | ---
Description: | Sets the connection to blocking or nonblocking mode.
Synopsis: |
    int tnscontrol(handle, cmd)
    void *handle;
    int *cmd;
Parameters: |

    handle(IN) - pointer to Net8 connection handle
    returned by tnsopen()
    cmd(IN) - option to apply to the connection.
    Currently supported values are:

    TNSAPINONBLOCKING - set connection into
    nonblocking mode
    TNSAPIBLOCKING - set connection into
    blocking mode
Prerequisites: | The handle must not be NULL, and cmd must be one of the supported commands.
Returns: | A zero value is returned if the option is successfully set.

### 11.1.2 Finding the Net8 OPEN Applications Program Interface

The applications program interface is provided as part of the standard Net8 installation. To use it, you need the following:

- TNSAPI.H - this is the header file which describes the API interfaces and errors. This file is located in the Oracle home directory for your platform. On UNIX, it is provided in $ORACLE_HOME/network/public.
- The Net8 OPEN library - located with other Oracle networking libraries, and contains the name "TNSAPI". Note that the name of the library varies by platform. On UNIX, it is in your $ORACLE_HOME/network/lib directory and is named libtnsapi.a. On Windows platforms, the Oracle directories contain the files TNSAPI.DLL and TNSAPI.LIB.
- Sample makefiles - are provided for your platform in your network directory. They can be used to determine the appropriate link line to build your application.

### 11.1.3 Building Your Own Application

Modules which make reference to Net8 OPEN functions should include TNSAPI.H, as follows:

    #include <tnsapi.h>

Your makefile (or other location for your build command) should ensure that the include path is set properly so that it can find TNSAPI.H. Refer to the sample makefiles provided in your installation.

### 11.1.4 Configuring the System to Use Your Net8 OPEN Application

To configure Net8 to recognize your Net8 OPEN application, proceed as follows:

1. Add the location of your server program to your listener configuration file (LISTENER.ORA), so that the network listener knows to start your server if a connection request is received.

   To do this, choose a system identifier (SID) name for your service similar to that of an Oracle database. Do not pick the same SID as your database.

   For example, if you are configuring a "chat" program, you could call the SID "chatsid". Place the program into the same place as the Oracle server executable, which is normally $ORACLE_HOME/bin, which we will assume here is in /usr/oracle/bin.

   You would place the following entry in a listener configuration file as follows:

       SID_LIST_LISTENER =

          (SID_LIST =

        (SID_DESC =

    (SID_NAME = chatsid)/*your SID name*/(ORACLE_HOME = /usr/oracle/
    bin)/*$ORACLE_HOME bin directory*/(PROGRAM = chatsvr)/*the name of
    your server program*/)

    You need to restart the listener, so it will recognize the new service.

    Add the address of your application server to your local names configuration file (TNSNAMES.ORA).

    For example, if your listener is listening on the following address:

    (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=unixhost)(PORT=1521)))

    And you want people to refer to the service you created above as "chat".

    You would add the following parameter to your local naming configuration file:

    chat=
    (DESCRIPTION=

    (ADDRESS=(PROTOCOL=tcp)(HOST=unixhost)(PORT=1521)
    )
    (CONNECT_DATA=(SID=chatsid)
    )

    )

    Note that the address contains the SID you configured in the LISTENER.ORA file above. Also note that the second line started with at least one space character, which indicates that it is a continuation line.

    If you have domains in your network, you need to name your service accordingly. For instance, use chat.acme.com if the domain is acme.com. Again, use the existing local naming configuration file as a template - if all the other service names end in a domain, you need to name your service similarly.

    Place the executable for your service in the same directory as your Oracle Server executable. On UNIX platforms, place the executable in the $ORACLE_HOME/bin directory indicated in your LISTENER.ORA file. In this example, you would place the program "chatsvr" in the location /usr/oracle/bin/chatsvr.

    If needed on your operating system, you also must ensure that you have permission to execute your program.

### 11.1.5 Sample Programs

Two sample applications are provided with Net8 OPEN:

- finger - this is a utility that connects to the server that retrieves information about who is logged in. This utility includes a pair of programs which demonstrate the basic steps involved in building a distributed application. The client program runs on both Solaris and Windows NT; the server is UNIX specific.
- tftp - this sample client and server program is implemented in UNIX to help you with simple file transfers using the tftp protocol.

### 11.1.6 Net8 OPEN API Errors

This section lists the error numbers which can be returned if one of the above function calls fails. Note that in some cases, connection-related errors may come back from a send or receive call, if the connection has not yet been established at that time.

    20002 - SDFAIL_TNSAPIE - The underlying "send" command failed in tnssend().
    20003 - RECVFAIL_TNSAPIE - The underlying "receive" command failed in tnsrecv().
    20004 - INVSVROP_TNSAPIE - Operation is invalid as the server.
    20005 - INVCLIOP_TNSAPIE - Operation is invalid as the client.
    20006 - HDLUNINI_TNSAPIE - The connection should be initialized by calling
    tnsopen().
    20007 - INHFAIL_TNSAPIE - Server failed in inheriting the connection from the
    listener.
    20008 - ACPTFAIL_TNSAPIE - Server failed in accepting the connection request
    from the client.
    20009 - NULHDL_TNSAPIE - A null handle was passed into the call, which is not
    allowed.
    20010 - INVOP_TNSAPIE - An invalid operation called was passed into the call.
    20011 - MALFAIL_TNSAPIE - A malloc failed in TNS API call.
    20012 - NLINIFAIL_TNSAPIE - Failed in NL initialization.
    20013 - NMTOOLONG_TNSAPIE - Service name is too long.
    20014 - CONFAIL_TNSAPIE - Client connect request failed.
    20015 - LSNFAIL_TNSAPIE - Server failed to listen for connect request.
    20016 - ANSFAIL_TNSAPIE - Server failed to answer connect request.
    20017 - NMRESFAIL_TNSAPIE - Failed to resolve service name.
    20018 - WOULDBLOCK_TNSAPIE - Operation would block.
    20019 - CTLFAIL_TNSAPIE - Control call failed.
    20020 - TNSAPIE_ERROR - TNS error occurred.
    20021 - INVCTL_TNSAPIE - Invalid operation request in control call.

## 11.2 UNIX Client Programming

Event programming in UNIX requires the use of a UNIX signal. When an event occurs, a signal flags a process. The process executes code that is relevant to the particular signal generated. UNIX does not allow a single process to set more than one signal handler or alarm for a particular signal call. If a process sets a second signal handler or alarm request on a signal like SIGCHLD (signal on a child process' status change), UNIX nullifies and loses the previous request for the SIGCHLD.

If any part of your application issues one of these requests, signal handling or alarms may cause the system to lose and never respond to that particular request. Depending on the signal requested, the system may not clean up defunct processes properly because of a signal handler problem.

Net8 provides two solutions to allow for the use of signal handling and alarms in tandem with Oracle's usage of those requests:

- Signal Handler and Alarm Programming
- Bequeath Adapter

### 11.2.1 Signal Handler and Alarm Programming

Net8 provides an operating system dependent (OSD) call that keeps a table of all signal handler or alarm requests for each signal. Any program that uses the signal handler or alarm is now required to use the Oracle OSD calls. This provides a solution for programmers in UNIX who are not allowed to set more than one signal handler or alarm for a particular call. Any program that uses the signal handler or alarm must use the Oracle OSD calls. This is however, currently available only for internal use. In the near future, an externalized version of the OSD calls for client application usage will be released.

Until then, if you set all of the client's signal handlers before making any database connections, the OSD call will remember the last signal handler set for the signal and will add it to the signal handler table. Note that by doing this, you cannot disable the signal handler.

#### 11.2.1.1 Oracle OSD Signal Handling Rules

To use the table-driven shared OSD signal handler for all SIGCHLD calls, you must observe the following rules:

- Know your child process IDs so you can clean up the correct process.
- Use the waitpid() call instead of wait() on the correct child process ID.
- The waitpid() call must be non-blocking.

### 11.2.2 Bequeath Adapter

This section is for UNIX application programmers who use both the UNIX signal handler for tracking child process status changes with the SIGCHLD call and Net8 for the networking portion of their application.

When a client application is directed to communicate with an Oracle database on the same machine, it uses Net8's Bequeath Adapter to establish the connection. The Bequeath Adapter enables the client to retrieve information from the database without using the network Listener. The Bequeath Adapter internally spawns a server process for each client application. In a sense, it performs locally the same operation that a remote listener does for your connection.

#### 11.2.2.1 Child Process Termination

Since the client application spawns a server process internally through the Bequeath Adapter as a child process, the client application becomes responsible for cleaning up the child process when it completes. When the server process completes its connection responsibilities, it becomes a defunct process. Signal handlers are responsible for cleaning up these defunct processes. Alternatively, you may configure your client profile to pass this process to the UNIX init process by disabling signal handlers.

Use the Oracle Net8 Assistant to configure a client to disable the UNIX signal handler. The profile parameter set to disable is as follows:

    BEQUEATH_DETACH=YES

This parameter causes all child processes to be passed over to the UNIX init process (pid = 1). The init process automatically checks for "defunct" child processes and terminates them.

The Bequeath Adapter automatically chooses to use a signal handler in tracking child process status changes. If your application does not use any signal handling, then this default does not affect you.

Prev | Next
| Copyright © 1997 Oracle Corporation. All Rights Reserved. |
Library | Product | Contents | Index