Most of the work performed by the socket layer is in sending and receiving data. The socket layer itself explicitly refrains from imposing any structure on data transmitted or received through sockets. Any data interpretation or structuring is logically isolated in the implementation of the communication domain.
Once a connection is established between sockets, an application program can send and receive data. Sending and receiving data can be done with any one of several subroutines. The subroutines vary according to the amount of information to be transmitted and received and the state of the socket being used to perform the operation.
The applicability of the above subroutines varies from domain to domain and from protocol to protocol.
While the send and recv subroutines are virtually identical to the read and write subroutines, the extra flags argument in the send and recv subroutines is important. The flags, defined in the sys/socket.h file, can be defined as a nonzero value if the application program requires one or more of the following:
MSG_OOB | Sends or receives out-of-band data. |
MSG_PEEK | Looks at data without reading. |
MSG_DONTROUTE | Sends data without routing packets. |
MSG_MPEG2 | Sends MPEG2 video data blocks. |
Out-of-band data is specific to stream sockets. The option to have data sent without routing applied to the outgoing packets is currently used only by the routing table management process, and is unlikely to be of interest to the casual user. The ability to preview data is, however, of general interest. When the MSG_PEEK flag is specified with a recv subroutine, any data present is returned to the user, but treated as still unread. That is, the next read or recv subroutine applied to the socket returns the data previously previewed.
The stream socket abstraction includes the concept of out-of-band data. Out-of-band (OOB) data is a logically independent transmission channel associated with each pair of connected stream sockets. Out-of-band data can be delivered to the socket independently of the normal receive queue or within the receive queue depending upon the status of the SO_OOBINLINE socket-level option. The abstraction defines that the out-of-band data facilities must support the reliable delivery of at least one out-of-band message at a time. This message must contain at least one byte of data, and at least one message can be pending delivery to the user at any one time.
For communication protocols that support only in-band signaling (that is, the urgent data is delivered in sequence with the normal data), the operating system normally extracts the data from the normal data stream and stores it separately. This allows users to choose between receiving the urgent data in order and receiving it out of sequence without having to buffer all the intervening data.
It is possible to peek at out-of-band data. If the socket has a process group, a SIGURG signal is generated when the protocol is notified of out-of-band data. A process can set the process group or process ID to be informed by the SIGURG signal through a SIOCSPGRP ioctl call.
Note: The /usr/include/sys/ioctl.h file contains the ioctl definitions and structures for use with socket ioctl calls.
If multiple sockets have out-of-band data awaiting delivery, an application program can use a select subroutine for exceptional conditions to determine those sockets with such data pending. Neither the signal nor the select indicates the actual arrival of the out-of-band data, but only notification that is pending.
In addition to the information passed, a logical mark is placed in the data stream to indicate the point at which the out-of-band data was sent. When a signal flushes any pending output, all data up to the mark in the data stream is discarded.
To send an out-of-band message, the MSG_OOB flag is supplied to a send or sendto subroutine. To receive out-of-band data, an application program must set the MSG_OOB flag when performing a recvfrom or recv subroutine.
An application program can determine if the read pointer is currently pointing at the logical mark in the data stream, by using the SIOCATMARK ioctl call.
A process can also read or peek at the out-of-band data without first reading up to the logical mark. This is more difficult when the underlying protocol delivers the urgent data in-band with the normal data, and only sends notification of its presence ahead of time (that is, the TCP protocol used to implement streams in the Internet domain). With such protocols, the out-of-band byte may not have arrived when a recv subroutine is performed with the MSG_OOB flag. In that case, the call will return an EWOULDBLOCK error code. There may be enough in-band data in the input buffer that normal flow control prevents the peer from sending the urgent data until the buffer is cleared. The process must then read enough of the queued data that the urgent data can be delivered.
Certain programs that use multiple bytes of urgent data and must handle multiple urgent signals need to retain the position of urgent data within the stream. The socket-level option, SO_OOINLINE provides the capability. With this option, the position of the urgent data (the logical mark) is retained. The urgent data immediately follows the mark within the normal data stream that is returned without the MSG_OOB flag. Reception of multiple urgent indications causes the mark to move, but no out-of-band data is lost.
Sockets can be set to either blocking or nonblocking I/O mode. The FIONBIO ioctl operation is used to determine this mode. When the FIONBIO ioctl is set, the socket is marked nonblocking. If a read is tried and the desired data is not available, the socket does not wait for the data to become available, but returns immediately with the EWOULDBLOCK error code.
Note: The EWOULDBLOCK error code is defined with the _BSD define and is equivalent to the EAGAIN error code.
When the FIONBIO ioctl is not set, the socket is in blocking mode. In this mode, if a read is tried and the desired data is not available, the calling process waits for the data. Similarly, when writing, if FIONBIO is set and the output queue is full, an attempt to write causes the process to return immediately with an error code of EWOULDBLOCK.
When performing nonblocking I/O on sockets, a program must check for the EWOULDBLOCK error code (stored in the errno global variable). This occurs when an operation would normally block, but the socket it was performed on is marked as nonblocking. The following socket subroutines return a EWOULDBLOCK error code:
Processes using these subroutines should be prepared to deal with the EWOULDBLOCK error code. For a nonblocking socket, the connect subroutine returns an EINPROGRESS error code.
If an operation such as a send operation cannot be done completely, but partial writes are permissible (for example when using a stream socket), the data that can be sent immediately is processed, and the return value indicates the amount actually sent.