home *** CD-ROM | disk | FTP | other *** search
- .\" Copyright (c) 1986 The Regents of the University of California.
- .\" All rights reserved.
- .\"
- .\" Redistribution and use in source and binary forms, with or without
- .\" modification, are permitted provided that the following conditions
- .\" are met:
- .\" 1. Redistributions of source code must retain the above copyright
- .\" notice, this list of conditions and the following disclaimer.
- .\" 2. Redistributions in binary form must reproduce the above copyright
- .\" notice, this list of conditions and the following disclaimer in the
- .\" documentation and/or other materials provided with the distribution.
- .\" 3. All advertising materials mentioning features or use of this software
- .\" must display the following acknowledgement:
- .\" This product includes software developed by the University of
- .\" California, Berkeley and its contributors.
- .\" 4. Neither the name of the University nor the names of its contributors
- .\" may be used to endorse or promote products derived from this software
- .\" without specific prior written permission.
- .\"
- .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- .\" SUCH DAMAGE.
- .\"
- .\" @(#)2.t 5.1 (Berkeley) 4/17/91
- .\"
- .\".ds RH "Basics
- .bp
- .nr H1 2
- .nr H2 0
- .bp
- .LG
- .B
- .ce
- 2. BASICS
- .sp 2
- .R
- .NL
- .PP
- The basic building block for communication is the \fIsocket\fP.
- A socket is an endpoint of communication to which a name may
- be \fIbound\fP. Each socket in use has a \fItype\fP
- and one or more associated processes. Sockets exist within
- \fIcommunication domains\fP.
- A communication domain is an
- abstraction introduced to bundle common properties of
- processes communicating through sockets.
- One such property is the scheme used to name sockets. For
- example, in the UNIX communication domain sockets are
- named with UNIX path names; e.g. a
- socket may be named \*(lq/dev/foo\*(rq. Sockets normally
- exchange data only with
- sockets in the same domain (it may be possible to cross domain
- boundaries, but only if some translation process is
- performed). The
- 4.3BSD IPC facilities support three separate communication domains:
- the UNIX domain, for on-system communication;
- the Internet domain, which is used by
- processes which communicate
- using the the DARPA standard communication protocols;
- and the NS domain, which is used by processes which
- communicate using the Xerox standard communication
- protocols*.
- .FS
- * See \fIInternet Transport Protocols\fP, Xerox System Integration
- Standard (XSIS)028112 for more information. This document is
- almost a necessity for one trying to write NS applications.
- .FE
- The underlying communication
- facilities provided by these domains have a significant influence
- on the internal system implementation as well as the interface to
- socket facilities available to a user. An example of the
- latter is that a socket \*(lqoperating\*(rq in the UNIX domain
- sees a subset of the error conditions which are possible
- when operating in the Internet (or NS) domain.
- .NH 2
- Socket types
- .PP
- Sockets are
- typed according to the communication properties visible to a
- user.
- Processes are presumed to communicate only between sockets of
- the same type, although there is
- nothing that prevents communication between sockets of different
- types should the underlying communication
- protocols support this.
- .PP
- Four types of sockets currently are available to a user.
- A \fIstream\fP socket provides for the bidirectional, reliable,
- sequenced, and unduplicated flow of data without record boundaries.
- Aside from the bidirectionality of data flow, a pair of connected
- stream sockets provides an interface nearly identical to that of pipes\(dg.
- .FS
- \(dg In the UNIX domain, in fact, the semantics are identical and,
- as one might expect, pipes have been implemented internally
- as simply a pair of connected stream sockets.
- .FE
- .PP
- A \fIdatagram\fP socket supports bidirectional flow of data which
- is not promised to be sequenced, reliable, or unduplicated.
- That is, a process
- receiving messages on a datagram socket may find messages duplicated,
- and, possibly,
- in an order different from the order in which it was sent.
- An important characteristic of a datagram
- socket is that record boundaries in data are preserved. Datagram
- sockets closely model the facilities found in many contemporary
- packet switched networks such as the Ethernet.
- .PP
- A \fIraw\fP socket provides users access to
- the underlying communication
- protocols which support socket abstractions.
- These sockets are normally datagram oriented, though their
- exact characteristics are dependent on the interface provided by
- the protocol. Raw sockets are not intended for the general user; they
- have been provided mainly for those interested in developing new
- communication protocols, or for gaining access to some of the more
- esoteric facilities of an existing protocol. The use of raw sockets
- is considered in section 5.
- .PP
- A \fIsequenced packet\fP socket is similar to a stream socket,
- with the exception that record boundaries are preserved. This
- interface is provided only as part of the NS socket abstraction,
- and is very important in most serious NS applications.
- Sequenced-packet sockets allow the user to manipulate the
- SPP or IDP headers on a packet or a group of packets either
- by writing a prototype header along with whatever data is
- to be sent, or by specifying a default header to be used with
- all outgoing data, and allows the user to receive the headers
- on incoming packets. The use of these options is considered in
- section 5.
- .PP
- Another potential socket type which has interesting properties is
- the \fIreliably delivered
- message\fP socket.
- The reliably delivered message socket has
- similar properties to a datagram socket, but with
- reliable delivery. There is currently no support for this
- type of socket, but a reliably delivered message protocol
- similar to Xerox's Packet Exchange Protocol (PEX) may be
- simulated at the user level. More information on this topic
- can be found in section 5.
- .NH 2
- Socket creation
- .PP
- To create a socket the \fIsocket\fP system call is used:
- .DS
- s = socket(domain, type, protocol);
- .DE
- This call requests that the system create a socket in the specified
- \fIdomain\fP and of the specified \fItype\fP. A particular protocol may
- also be requested. If the protocol is left unspecified (a value
- of 0), the system will select an appropriate protocol from those
- protocols which comprise the communication domain and which
- may be used to support the requested socket type. The user is
- returned a descriptor (a small integer number) which may be used
- in later system calls which operate on sockets. The domain is specified as
- one of the manifest constants defined in the file <\fIsys/socket.h\fP>.
- For the UNIX domain the constant is AF_UNIX*; for the Internet
- .FS
- * The manifest constants are named AF_whatever as they indicate
- the ``address format'' to use in interpreting names.
- .FE
- domain AF_INET; and for the NS domain, AF_NS.
- The socket types are also defined in this file
- and one of SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, or SOCK_SEQPACKET
- must be specified.
- To create a stream socket in the Internet domain the following
- call might be used:
- .DS
- s = socket(AF_INET, SOCK_STREAM, 0);
- .DE
- This call would result in a stream socket being created with the TCP
- protocol providing the underlying communication support. To
- create a datagram socket for on-machine use the call might
- be:
- .DS
- s = socket(AF_UNIX, SOCK_DGRAM, 0);
- .DE
- .PP
- The default protocol (used when the \fIprotocol\fP argument to the
- \fIsocket\fP call is 0) should be correct for most every
- situation. However, it is possible to specify a protocol
- other than the default; this will be covered in
- section 5.
- .PP
- There are several reasons a socket call may fail. Aside from
- the rare occurrence of lack of memory (ENOBUFS), a socket
- request may fail due to a request for an unknown protocol
- (EPROTONOSUPPORT), or a request for a type of socket for
- which there is no supporting protocol (EPROTOTYPE).
- .NH 2
- Binding local names
- .PP
- A socket is created without a name. Until a name is bound
- to a socket, processes have no way to reference it and, consequently,
- no messages may be received on it.
- Communicating processes are bound
- by an \fIassociation\fP. In the Internet and NS domains,
- an association
- is composed of local and foreign
- addresses, and local and foreign ports,
- while in the UNIX domain, an association is composed of
- local and foreign path names (the phrase ``foreign pathname''
- means a pathname created by a foreign process, not a pathname
- on a foreign system).
- In most domains, associations must be unique.
- In the Internet domain there
- may never be duplicate <protocol, local address, local port, foreign
- address, foreign port> tuples. UNIX domain sockets need not always
- be bound to a name, but when bound
- there may never be duplicate <protocol, local pathname, foreign
- pathname> tuples.
- The pathnames may not refer to files
- already existing on the system
- in 4.3; the situation may change in future releases.
- .PP
- The \fIbind\fP system call allows a process to specify half of
- an association, <local address, local port>
- (or <local pathname>), while the \fIconnect\fP
- and \fIaccept\fP primitives are used to complete a socket's association.
- .PP
- In the Internet domain,
- binding names to sockets can be fairly complex.
- Fortunately, it is usually not necessary to specifically bind an
- address and port number to a socket, because the
- \fIconnect\fP and \fIsend\fP calls will automatically
- bind an appropriate address if they are used with an
- unbound socket. The process of binding names to NS
- sockets is similar in most ways to that of
- binding names to Internet sockets.
- .PP
- The \fIbind\fP system call is used as follows:
- .DS
- bind(s, name, namelen);
- .DE
- The bound name is a variable length byte string which is interpreted
- by the supporting protocol(s). Its interpretation may vary from
- communication domain to communication domain (this is one of
- the properties which comprise the \*(lqdomain\*(rq).
- As mentioned, in the
- Internet domain names contain an Internet address and port
- number. NS domain names contain an NS address and
- port number. In the UNIX domain, names contain a path name and
- a family, which is always AF_UNIX. If one wanted to bind
- the name \*(lq/tmp/foo\*(rq to a UNIX domain socket, the
- following code would be used*:
- .FS
- * Note that, although the tendency here is to call the \*(lqaddr\*(rq
- structure \*(lqsun\*(rq, doing so would cause problems if the code
- were ever ported to a Sun workstation.
- .FE
- .DS
- #include <sys/un.h>
- ...
- struct sockaddr_un addr;
- ...
- strcpy(addr.sun_path, "/tmp/foo");
- addr.sun_family = AF_UNIX;
- bind(s, (struct sockaddr *) &addr, strlen(addr.sun_path) +
- sizeof (addr.sun_family));
- .DE
- Note that in determining the size of a UNIX domain address null
- bytes are not counted, which is why \fIstrlen\fP is used. In
- the current implementation of UNIX domain IPC under 4.3BSD,
- the file name
- referred to in \fIaddr.sun_path\fP is created as a socket
- in the system file space.
- The caller must, therefore, have
- write permission in the directory where
- \fIaddr.sun_path\fP is to reside, and this file should be deleted by the
- caller when it is no longer needed. Future versions of 4BSD
- may not create this file.
- .PP
- In binding an Internet address things become more
- complicated. The actual call is similar,
- .DS
- #include <sys/types.h>
- #include <netinet/in.h>
- ...
- struct sockaddr_in sin;
- ...
- bind(s, (struct sockaddr *) &sin, sizeof (sin));
- .DE
- but the selection of what to place in the address \fIsin\fP
- requires some discussion. We will come back to the problem
- of formulating Internet addresses in section 3 when
- the library routines used in name resolution are discussed.
- .PP
- Binding an NS address to a socket is even more
- difficult,
- especially since the Internet library routines do not
- work with NS hostnames. The actual call is again similar:
- .DS
- #include <sys/types.h>
- #include <netns/ns.h>
- ...
- struct sockaddr_ns sns;
- ...
- bind(s, (struct sockaddr *) &sns, sizeof (sns));
- .DE
- Again, discussion of what to place in a \*(lqstruct sockaddr_ns\*(rq
- will be deferred to section 3.
- .NH 2
- Connection establishment
- .PP
- Connection establishment is usually asymmetric,
- with one process a \*(lqclient\*(rq and the other a \*(lqserver\*(rq.
- The server, when willing to offer its advertised services,
- binds a socket to a well-known address associated with the service
- and then passively \*(lqlistens\*(rq on its socket.
- It is then possible for an unrelated process to rendezvous
- with the server.
- The client requests services from the server by initiating a
- \*(lqconnection\*(rq to the server's socket.
- On the client side the \fIconnect\fP call is
- used to initiate a connection. Using the UNIX domain, this
- might appear as,
- .DS
- struct sockaddr_un server;
- ...
- connect(s, (struct sockaddr *)&server, strlen(server.sun_path) +
- sizeof (server.sun_family));
- .DE
- while in the Internet domain,
- .DS
- struct sockaddr_in server;
- ...
- connect(s, (struct sockaddr *)&server, sizeof (server));
- .DE
- and in the NS domain,
- .DS
- struct sockaddr_ns server;
- ...
- connect(s, (struct sockaddr *)&server, sizeof (server));
- .DE
- where \fIserver\fP in the example above would contain either the UNIX
- pathname, Internet address and port number, or NS address and
- port number of the server to which the
- client process wishes to speak.
- If the client process's socket is unbound at the time of
- the connect call,
- the system will automatically select and bind a name to
- the socket if necessary; c.f. section 5.4.
- This is the usual way that local addresses are bound
- to a socket.
- .PP
- An error is returned if the connection was unsuccessful
- (any name automatically bound by the system, however, remains).
- Otherwise, the socket is associated with the server and
- data transfer may begin. Some of the more common errors returned
- when a connection attempt fails are:
- .IP ETIMEDOUT
- .br
- After failing to establish a connection for a period of time,
- the system decided there was no point in retrying the
- connection attempt any more. This usually occurs because
- the destination host is down, or because problems in
- the network resulted in transmissions being lost.
- .IP ECONNREFUSED
- .br
- The host refused service for some reason.
- This is usually
- due to a server process
- not being present at the requested name.
- .IP "ENETDOWN or EHOSTDOWN"
- .br
- These operational errors are
- returned based on status information delivered to
- the client host by the underlying communication services.
- .IP "ENETUNREACH or EHOSTUNREACH"
- .br
- These operational errors can occur either because the network
- or host is unknown (no route to the network or host is present),
- or because of status information returned by intermediate
- gateways or switching nodes. Many times the status returned
- is not sufficient to distinguish a network being down from a
- host being down, in which case the system
- indicates the entire network is unreachable.
- .PP
- For the server to receive a client's connection it must perform
- two steps after binding its socket.
- The first is to indicate a willingness to listen for
- incoming connection requests:
- .DS
- listen(s, 5);
- .DE
- The second parameter to the \fIlisten\fP call specifies the maximum
- number of outstanding connections which may be queued awaiting
- acceptance by the server process; this number
- may be limited by the system. Should a connection be
- requested while the queue is full, the connection will not be
- refused, but rather the individual messages which comprise the
- request will be ignored. This gives a harried server time to
- make room in its pending connection queue while the client
- retries the connection request. Had the connection been returned
- with the ECONNREFUSED error, the client would be unable to tell
- if the server was up or not. As it is now it is still possible
- to get the ETIMEDOUT error back, though this is unlikely. The
- backlog figure supplied with the listen call is currently limited
- by the system to a maximum of 5 pending connections on any
- one queue. This avoids the problem of processes hogging system
- resources by setting an infinite backlog, then ignoring
- all connection requests.
- .PP
- With a socket marked as listening, a server may \fIaccept\fP
- a connection:
- .DS
- struct sockaddr_in from;
- ...
- fromlen = sizeof (from);
- newsock = accept(s, (struct sockaddr *)&from, &fromlen);
- .DE
- (For the UNIX domain, \fIfrom\fP would be declared as a
- \fIstruct sockaddr_un\fP, and for the NS domain, \fIfrom\fP
- would be declared as a \fIstruct sockaddr_ns\fP,
- but nothing different would need
- to be done as far as \fIfromlen\fP is concerned. In the examples
- which follow, only Internet routines will be discussed.) A new
- descriptor is returned on receipt of a connection (along with
- a new socket). If the server wishes to find out who its client is,
- it may supply a buffer for the client socket's name. The value-result
- parameter \fIfromlen\fP is initialized by the server to indicate how
- much space is associated with \fIfrom\fP, then modified on return
- to reflect the true size of the name. If the client's name is not
- of interest, the second parameter may be a null pointer.
- .PP
- \fIAccept\fP normally blocks. That is, \fIaccept\fP
- will not return until a connection is available or the system call
- is interrupted by a signal to the process. Further, there is no
- way for a process to indicate it will accept connections from only
- a specific individual, or individuals. It is up to the user process
- to consider who the connection is from and close down the connection
- if it does not wish to speak to the process. If the server process
- wants to accept connections on more than one socket, or wants to avoid blocking
- on the accept call, there are alternatives; they will be considered
- in section 5.
- .NH 2
- Data transfer
- .PP
- With a connection established, data may begin to flow. To send
- and receive data there are a number of possible calls.
- With the peer entity at each end of a connection
- anchored, a user can send or receive a message without specifying
- the peer. As one might expect, in this case, then
- the normal \fIread\fP and \fIwrite\fP system calls are usable,
- .DS
- write(s, buf, sizeof (buf));
- read(s, buf, sizeof (buf));
- .DE
- In addition to \fIread\fP and \fIwrite\fP,
- the new calls \fIsend\fP and \fIrecv\fP
- may be used:
- .DS
- send(s, buf, sizeof (buf), flags);
- recv(s, buf, sizeof (buf), flags);
- .DE
- While \fIsend\fP and \fIrecv\fP are virtually identical to
- \fIread\fP and \fIwrite\fP,
- the extra \fIflags\fP argument is important. The flags,
- defined in \fI<sys/socket.h>\fP, may be
- specified as a non-zero value if one or more
- of the following is required:
- .DS
- .TS
- l l.
- MSG_OOB send/receive out of band data
- MSG_PEEK look at data without reading
- MSG_DONTROUTE send data without routing packets
- .TE
- .DE
- Out of band data is a notion specific to stream sockets, and one
- which we will not immediately consider. 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 interest. When MSG_PEEK
- is specified with a \fIrecv\fP call, any data present is returned
- to the user, but treated as still \*(lqunread\*(rq. That
- is, the next \fIread\fP or \fIrecv\fP call applied to the socket will
- return the data previously previewed.
- .NH 2
- Discarding sockets
- .PP
- Once a socket is no longer of interest, it may be discarded
- by applying a \fIclose\fP to the descriptor,
- .DS
- close(s);
- .DE
- If data is associated with a socket which promises reliable delivery
- (e.g. a stream socket) when a close takes place, the system will
- continue to attempt to transfer the data.
- However, after a fairly long period of
- time, if the data is still undelivered, it will be discarded.
- Should a user have no use for any pending data, it may
- perform a \fIshutdown\fP on the socket prior to closing it.
- This call is of the form:
- .DS
- shutdown(s, how);
- .DE
- where \fIhow\fP is 0 if the user is no longer interested in reading
- data, 1 if no more data will be sent, or 2 if no data is to
- be sent or received.
- .NH 2
- Connectionless sockets
- .PP
- To this point we have been concerned mostly with sockets which
- follow a connection oriented model. However, there is also
- support for connectionless interactions typical of the datagram
- facilities found in contemporary packet switched networks.
- A datagram socket provides a symmetric interface to data
- exchange. While processes are still likely to be client
- and server, there is no requirement for connection establishment.
- Instead, each message includes the destination address.
- .PP
- Datagram sockets are created as before.
- If a particular local address is needed,
- the \fIbind\fP operation must precede the first data transmission.
- Otherwise, the system will set the local address and/or port
- when data is first sent.
- To send data, the \fIsendto\fP primitive is used,
- .DS
- sendto(s, buf, buflen, flags, (struct sockaddr *)&to, tolen);
- .DE
- The \fIs\fP, \fIbuf\fP, \fIbuflen\fP, and \fIflags\fP
- parameters are used as before.
- The \fIto\fP and \fItolen\fP
- values are used to indicate the address of the intended recipient of the
- message. When
- using an unreliable datagram interface, it is
- unlikely that any errors will be reported to the sender. When
- information is present locally to recognize a message that can
- not be delivered (for instance when a network is unreachable),
- the call will return \-1 and the global value \fIerrno\fP will
- contain an error number.
- .PP
- To receive messages on an unconnected datagram socket, the
- \fIrecvfrom\fP primitive is provided:
- .DS
- recvfrom(s, buf, buflen, flags, (struct sockaddr *)&from, &fromlen);
- .DE
- Once again, the \fIfromlen\fP parameter is handled in
- a value-result fashion, initially containing the size of
- the \fIfrom\fP buffer, and modified on return to indicate
- the actual size of the address from which the datagram was received.
- .PP
- In addition to the two calls mentioned above, datagram
- sockets may also use the \fIconnect\fP call to associate
- a socket with a specific destination address. In this case, any
- data sent on the socket will automatically be addressed
- to the connected peer, and only data received from that
- peer will be delivered to the user. Only one connected
- address is permitted for each socket at one time;
- a second connect will change the destination address,
- and a connect to a null address (family AF_UNSPEC)
- will disconnect.
- Connect requests on datagram sockets return immediately,
- as this simply results in the system recording
- the peer's address (as compared to a stream socket, where a
- connect request initiates establishment of an end to end
- connection). \fIAccept\fP and \fIlisten\fP are not
- used with datagram sockets.
- .PP
- While a datagram socket socket is connected,
- errors from recent \fIsend\fP calls may be returned
- asynchronously.
- These errors may be reported on subsequent operations
- on the socket,
- or a special socket option used with \fIgetsockopt\fP, SO_ERROR,
- may be used to interrogate the error status.
- A \fIselect\fP for reading or writing will return true
- when an error indication has been received.
- The next operation will return the error, and the error status is cleared.
- Other of the less
- important details of datagram sockets are described
- in section 5.
- .NH 2
- Input/Output multiplexing
- .PP
- One last facility often used in developing applications
- is the ability to multiplex i/o requests among multiple
- sockets and/or files. This is done using the \fIselect\fP
- call:
- .DS
- #include <sys/time.h>
- #include <sys/types.h>
- ...
-
- fd_set readmask, writemask, exceptmask;
- struct timeval timeout;
- ...
- select(nfds, &readmask, &writemask, &exceptmask, &timeout);
- .DE
- \fISelect\fP takes as arguments pointers to three sets, one for
- the set of file descriptors for which the caller wishes to
- be able to read data on, one for those descriptors to which
- data is to be written, and one for which exceptional conditions
- are pending; out-of-band data is the only
- exceptional condition currently implemented by the socket
- If the user is not interested
- in certain conditions (i.e., read, write, or exceptions),
- the corresponding argument to the \fIselect\fP should
- be a null pointer.
- .PP
- Each set is actually a structure containing an array of
- long integer bit masks; the size of the array is set
- by the definition FD_SETSIZE.
- The array is be
- long enough to hold one bit for each of FD_SETSIZE file descriptors.
- .PP
- The macros FD_SET(\fIfd, &mask\fP) and
- FD_CLR(\fIfd, &mask\fP)
- have been provided for adding and removing file descriptor
- \fIfd\fP in the set \fImask\fP. The
- set should be zeroed before use, and
- the macro FD_ZERO(\fI&mask\fP) has been provided
- to clear the set \fImask\fP.
- The parameter \fInfds\fP in the \fIselect\fP call specifies the range
- of file descriptors (i.e. one plus the value of the largest
- descriptor) to be examined in a set.
- .PP
- A timeout value may be specified if the selection
- is not to last more than a predetermined period of time. If
- the fields in \fItimeout\fP are set to 0, the selection takes
- the form of a
- \fIpoll\fP, returning immediately. If the last parameter is
- a null pointer, the selection will block indefinitely*.
- .FS
- * To be more specific, a return takes place only when a
- descriptor is selectable, or when a signal is received by
- the caller, interrupting the system call.
- .FE
- \fISelect\fP normally returns the number of file descriptors selected;
- if the \fIselect\fP call returns due to the timeout expiring, then
- the value 0 is returned.
- If the \fIselect\fP terminates because of an error or interruption,
- a \-1 is returned with the error number in \fIerrno\fP,
- and with the file descriptor masks unchanged.
- .PP
- Assuming a successful return, the three sets will
- indicate which
- file descriptors are ready to be read from, written to, or
- have exceptional conditions pending.
- The status of a file descriptor in a select mask may be
- tested with the \fIFD_ISSET(fd, &mask)\fP macro, which
- returns a non-zero value if \fIfd\fP is a member of the set
- \fImask\fP, and 0 if it is not.
- .PP
- To determine if there are connections waiting
- on a socket to be used with an \fIaccept\fP call,
- \fIselect\fP can be used, followed by
- a \fIFD_ISSET(fd, &mask)\fP macro to check for read
- readiness on the appropriate socket. If \fIFD_ISSET\fP
- returns a non-zero value, indicating permission to read, then a
- connection is pending on the socket.
- .PP
- As an example, to read data from two sockets, \fIs1\fP and
- \fIs2\fP as it is available from each and with a one-second
- timeout, the following code
- might be used:
- .DS
- #include <sys/time.h>
- #include <sys/types.h>
- ...
- fd_set read_template;
- struct timeval wait;
- ...
- for (;;) {
- wait.tv_sec = 1; /* one second */
- wait.tv_usec = 0;
-
- FD_ZERO(&read_template);
-
- FD_SET(s1, &read_template);
- FD_SET(s2, &read_template);
-
- nb = select(FD_SETSIZE, &read_template, (fd_set *) 0, (fd_set *) 0, &wait);
- if (nb <= 0) {
- \fIAn error occurred during the \fPselect\fI, or
- the \fPselect\fI timed out.\fP
- }
-
- if (FD_ISSET(s1, &read_template)) {
- \fISocket #1 is ready to be read from.\fP
- }
-
- if (FD_ISSET(s2, &read_template)) {
- \fISocket #2 is ready to be read from.\fP
- }
- }
- .DE
- .PP
- In 4.2, the arguments to \fIselect\fP were pointers to integers
- instead of pointers to \fIfd_set\fPs. This type of call
- will still work as long as the number of file descriptors
- being examined is less than the number of bits in an
- integer; however, the methods illustrated above should
- be used in all current programs.
- .PP
- \fISelect\fP provides a synchronous multiplexing scheme.
- Asynchronous notification of output completion, input availability,
- and exceptional conditions is possible through use of the
- SIGIO and SIGURG signals described in section 5.
-