HPlogo HP 9000 Networking: BSD Sockets Interface Programmer's Guide > Chapter 3 Advanced Topics for Stream Sockets

Sending and Receiving Out-of-band Data

» 

Technical documentation

Complete book in PDF

 » Table of Contents

 » Glossary

 » Index

This option is not supported for UNIX Domain (AF_UNIX) sockets.

If an abnormal condition occurs when a process is in the middle of sending a long stream of data, it is useful to be able to alert the other process with an urgent message. The TCP stream socket implementation includes an out-of-band data facility. Out-of-band data uses a logically independent transmission channel associated with a pair of connected stream sockets. TCP supports the reliable delivery of only one out-of-band message at a time. The message can be a maximum of one byte long.

Out-of-band data arrive at the destination node in sequence and in stream, but are delivered independently of normal data. If the receiver has enabled the signalling of out-of-band data via the SIOCSPGRP socket ioctl (see the socket(7) man page), then a SIGURG is delivered when out-of-band data arrive. If the receiver is selecting for exceptional conditions on the receiving socket, it will return true to signal the arrival of out-of-band data. The receiving process can read the out-of-band message and take the appropriate action based on the message contents. A logical mark is placed in the normal data stream to indicate the point at which the out-of-band data were sent, so that data before the message can be handled differently from data following the message. Here is a data stream with an out-of-band marker:

byte stream <----- data

oob mark

data <--------

For a program to know when out-of-band data are available to be received, you may arrange the program to catch the SIGURG signal as follows:

struct sigvec vec;
int onurg();
int pid, s;

/*
** arrange for onurg() to be called when SIGURG is received:
*/
vec.sv_handler = onurg;
vec.sv_mask = 0;
vec.sv_onstack = 0;
if (sigvector(SIGURG, &vec, (struct sigvec *) 0) < 0) {
perror("sigvector(SIGURG)");
}

onurg() is a routine that handles out-of-band data in the client program.

In addition, the socket's process group must be set, as shown below. The kernel will not send the signal to the process (or process group) unless this is done, even though the signal handler has been enabled. Refer to the socket(7) man page for more details.

/*
** arrange for the current process to receive SIGURG
** when the socket s has urgent data:
*/
pid = getpid();
if (ioctl(s, SIOCSPGRP, (char *) &pid) < 0) {
perror("ioctl(SIOCSPGRP)");
}
/*
** If a process needs to be notified, it should be
** pid = -getpgrp();
*/

If the server process is sending data to the client process, and a problem occurs, the server can send an out-of-band data byte by executing a send with the MSG_OOB flag set. This sends the out-of-band data and a SIGURG signal to the receiving process.

send(sd, &msg, 1, MSG_OOB)

When a SIGURG signal is received, onurg is called. onurg receives the out-of-band data byte with the MSG_OOB flag set on a recv call.

It is possible that the out-of-band byte has not arrived when the SIGURG signal arrives. recv never blocks on a receive of out-of-band data, so the client may need to repeat the recv call until the out-of-band byte arrives. recv will return EINVAL if the out-of-band data is not available.

Generally, the out-of-band data byte is stored independently from the normal data stream. If, however, the OOB_INLINE socket option has been turned on for this socket, the out-of-band data will remain inline and must be used without the MSG_OOB flag set on a recv() call.

You cannot read past the out-of-band pointer location in one recv call. If you request more data than the amount queued on the socket before the out-of-band pointer, then recv will return only the data up to the out-of-band pointer. However, once you read past the out-of-band pointer location with subsequent recv calls, the out-of-band byte can no longer be read.

Usually the out-of-band data message indicates that all data currently in the stream can be flushed. This involves moving the stream pointer with successive recv calls, to the location of the out-of-band data pointer.

The request SIOCATMARK informs you, as you receive data from the stream, when the stream pointer has reached the out-of-band pointer. If ioctl returns a 0, the next recv provides data sent by the server prior to transmission of the out-of-band data. ioctl returns a 1 when the stream pointer reaches the out-of-band byte pointer. The next recv provides data sent by the server after the out-of-band message. The following shows how the SIOCATMARK request can be used in a SIGURG interrupt handler.

/*  s is the socket with urgent data  */

onurg()
{
int atmark;
char mark;
char flush [100];

while (1) {
/*
** check whether we have read the stream
** up to the OOB mark yet
*/
if (ioctl(s, SIOCATMARK, &atmark) < 0) {
/* if the ioctl failed */
perror("ioctl(SIOCATMARK)");
return;
}
if (atmark) {
/* we have read the stream up to the OOB mark */
break;
}
/*
** read the stream data preceding the mark,
** only to throw it away
*/
if (read(s, flush, sizeof(flush)) <= 0) {
/* if the read failed */
return;
}
}
/*
** receive the OOB byte
*/
recv(s, &mark, 1, MSG_OOB);

printf("received %c OOB\n", mark);
return;
}
© 1997 Hewlett-Packard Development Company, L.P.