Sun Microsystems, Inc.
spacerspacer
spacer www.sun.com docs.sun.com |
spacer
black dot
 
 
7.  Programming With XTI and TLI Asynchronous Networking Asynchronous Connectionless-Mode Service Asynchronous Network Transfers  Previous   Contents   Next 
   
 

Asynchronous Connection-Mode Service

For connection-mode service, an application can arrange not only for the data transfer, but also for the establishment of the connection itself to be done asynchronously. The sequence of operations depends on whether the process is attempting to connect to another process or is awaiting connection attempts.

Asynchronously Establishing a Connection

A process can attempt a connection and asynchronously complete the connection. The process first creates the connecting endpoint and, using fcntl(2), configures the endpoint for non-blocking operation. As with connectionless data transfers, the endpoint can also be configured for asynchronous notification upon completion of the connection and subsequent data transfers. The connecting process then uses t_connect(3NSL) to initiate setting up the transfer. Then t_rcvconnect(3NSL) is used to confirm the establishment of the connection.

Asynchronous Use of a Connection

To asynchronously await connections, a process first establishes a non-blocking endpoint bound to a service address. When either the result of poll(2) or an asynchronous notification indicates that a connection request has arrived, the process can get the connection request by using t_listen(3NSL) . To accept the connection, the process uses t_accept(3NSL) . The responding endpoint must be separately configured for asynchronous data transfers.

The following example illustrates how to request a connection asynchronously.

#include <tiuser.h>
int             fd;
struct t_call   *call;

	fd = .../* establish a non-blocking endpoint */

	call = (struct t_call *) t_alloc(fd, T_CALL, T_ADDR);
	.../* initialize call structure */
	t_connect(fd, call, call);

	/* connection request is now proceeding asynchronously */

	.../* receive indication that connection has been accepted */
	t_rcvconnect(fd, &call);

The following example illustrates listening for connections asynchronously.

#include <tiuser.h>
int             fd, res_fd;
struct t_call   call;

	fd = ... /* establish non-blocking endpoint */

	.../*receive indication that connection request has arrived
*/
	call = (struct t_call *) t_alloc(fd, T_CALL, T_ALL);
	t_listen(fd, &call);

	.../* determine whether or not to accept connection */
	res_fd = ... /* establish non-blocking endpoint for response
*/
	t_accept(fd, res_fd, call);

Asynchronous Open

Occasionally, an application might be required to dynamically open a regular file in a file system mounted from a remote host, or on a device whose initialization might be prolonged. However, while such a request to open a file is being processed, the application is unable to achieve real-time response to other events. The SunOS software solves this problem by having a second process handle the actual opening of the file, then passes the file descriptor to the real-time process.

Transferring a File Descriptor

The STREAMS interface provided by the SunOS platform provides a mechanism for passing an open file descriptor from one process to another. The process with the open file descriptor uses ioctl(2) with a command argument of I_SENDFD. The second process obtains the file descriptor by calling ioctl(2) with a command argument of I_RECVFD.

In the following example, the parent process prints out information about the test file, and creates a pipe. Next, the parent creates a child process that opens the test file and passes the open file descriptor back to the parent through the pipe. The parent process then displays the status information on the new file descriptor.


Example 7-6 File Descriptor Transfer

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stropts.h>
#include <stdio.h>

#define TESTFILE "/dev/null"
main(int argc, char *argv[])
{
	int fd;
	int pipefd[2];
	struct stat statbuf;

	stat(TESTFILE, &statbuf);
	statout(TESTFILE, &statbuf);
	pipe(pipefd);
	if (fork() == 0) {
		close(pipefd[0]);
		sendfd(pipefd[1]);
	} else {
		close(pipefd[1])
		recvfd(pipefd[0]);
	}
}

sendfd(int p)
{
	int tfd;

	tfd = open(TESTFILE, O_RDWR);
	ioctl(p, I_SENDFD, tfd);
}

recvfd(int p)
{
	struct strrecvfd rfdbuf;
	struct stat statbuf;
	char			fdbuf[32];

	ioctl(p, I_RECVFD, &rfdbuf);
	fstat(rfdbuf.fd, &statbuf);
	sprintf(fdbuf, "recvfd=%d", rfdbuf.fd);
	statout(fdbuf, &statbuf);	
}

statout(char *f, struct stat *s)
{
	printf("stat: from=%s mode=0%o, ino=%ld, dev=%lx, rdev=%lx\n",
		f, s->st_mode, s->st_ino, s->st_dev, s->st_rdev);
	fflush(stdout);
}

State Transitions

The tables in the following sections describe all state transitions associated with XTI/TLI.

 
 
 
  Previous   Contents   Next