Sunday, August 28, 2011

Associating a Socket with a Stream


The stdio(3) stream is managed through the FILE control block. For example, you've probably already written code that looks something like this many times:

Example

FILE *in;
in = fopen(pathname,"r");
if ( in == NULL ) {
   fprintf(stderr,"%s: opening %s for
           read.\n",strerror(errno),pathname);
   exit(1);
}
In the example presented, the file known as variable pathname is opened for reading. If the open call succeeds, the variable in receives a pointer to the FILE structure, which manages the stream I/O for you. Otherwise, variable in receives a null pointer, and your application must handle or report the error. For socket programming, however, there is no stdio(3) call available to open a socket. How then does a programmer accomplish associating a stream with a socket? Read the next section to find out.

Using fdopen(3) to Associate a Socket with a Stream

The function call fopen(3) should be quite familiar to you. However, for many, the fdopen(3) call is new or unfamiliar. Because this function is likely to be new to some of you, let's introduce its function synopsis and describe it:

#include <stdio.h>
FILE *fdopen(int fildes, const char *mode);

This function takes two arguments:
  1. An integer file descriptor (fildes) to use for performing I/O.
  2. The standard I/O mode to use. This will be an open mode, which is the same as the familiar fopen(3) mode argument. For example, "r" indicates that the stream is to be opened for reading, whereas "w" indicates the stream is to be opened for writing.

Like the fopen(3) call, if the function is successful, a pointer to the controlling FILE structure is returned. Otherwise, a null pointer indicates that a problem developed, and external variable errno will contain the nature of the error.

Note that the first argument was a file descriptor. You will recall that the socket returned from the socket(2) function is also a file descriptor. This then makes it possible to associate any existing socket to a stream. Listing 10.1 shows a short example of associating a socket to a stream that can be read or written.

Example
/*
 * Listing 10.1: Associating a Socket with a Stream
 */
int s; // socket
FILE *io; // stream
s = socket(PF_INET,SOCK_STREAM,0);
. . .
io = fdopen(s,"r+");
if ( io == NULL ) {
   fprintf(stderr,"%s: fdopen(s)\n",strerror(errno));
   exit(1);
}

Listing 10.1 demonstrates how the socket number, which was held in variable s, was associated with a FILE stream named io. The mode argument of the fdopen(3) call in this example established a stream for input and output. After this open call has been successfully accomplished, the other standard I/O functions such as fgetc(3), for example, can be employed.

No comments:

Post a Comment