| < Day Day Up > |
|
Handling return errors from Sockets functions is a common mistake found in many Sockets applications. A simple way to identify whether a peer socket has closed its connection is to check the return status of Sockets functions.
When the peer closes its socket, either intentionally or unintentionally, the proper action is to detect the closure and permit the application to take the necessary action. This is commonly closing the socket and then attempting to reconnect (if needed).
Detecting a peer socket close is commonly performed with data input/output functions (send, recv, sendto, recvfrom, read, write). The input functions return a zero on peer socket closure, whereas output functions return an error (commonly broken-pipe). The following code snippets (Listing 6.3 and Listing 6.4) illustrate detecting peer closure for read and write.
Listing 6.3 Detecting peer closure using input calls.
int sock, ret; char buffer[MAX_BUFFER_SIZE+1]; sock = socket( AF_INET, SOCK_STREAM, 0 ); /* Client connect... */ ret = recv( sock, buffer, MAX_BUFFER_SIZE, 0 ); if ( ret > 0 ) { /* Received data, deal with it accordingly */ } else if ( ret < 0 ) { /* An error occurred, check error status */ } else if ( ret == 0 ) { /* Peer closed, error leg */ close( sock ); }
In Listing 6.3, after a return of zero is detected from the recv call, the socket is unusable. Clients commonly close the socket and attempt a reconnect, whereas servers simply close the connection and await a reconnect.
The peer socket closure can also be detected through a write function, such as is shown in Listing 6.4. In this case, an error results from the write and the error status must be checked to identify whether the peer socket closed or if some other error occurred. In Unix systems, the error value that results from peer closure is EPIPE (pipe broken). Additionally, Unix systems typically generate a signal.
Listing 6.4 Detecting peer closure using output calls.
int servsock, clisock, ret, size; char buffer[MAX_BUFFER_SIZE+1]; servsock = socket( AF_INET, SOCK_STREAM, 0 ); /* Server setup... */ clisock = accept( servsock, (struct sockaddr *)NULL, NULL ); /* buffer setup for size... */ ret = write( sock, buffer, size, 0 ); if ( ret == size ) { /* Data written */ } else if ( ret < 0 ) { /* An error occurred, check error status */ if ( errno == EPIPE ) { /* Peer closed */ close( clisock ); } }
Handling this kind of error is necessary in any Sockets application. An application can’t guarantee the behavior of the remote application nor can it guarantee the reliability of the network; therefore, detecting peer closure is essential.
| < Day Day Up > |
|