This guide assumes some knowledge of TCP/IP programming using the BSD Sockets abstraction. It does not attempt a thorough introduce to this subject. For detailed information on BSD Sockets, the programmer is referred to:
Internetworking with TCP/IP, Volume III: Client-Server Programming and Applications, Second edition (BSD Socket version with ANSI C)
Douglas E. Comer and David L. Stevens, Prentice Hall
ISBN 0-13-260969-X
These advanced facilities of the PsiStack SDK are mentioned here;
the reader is referred to the appropriate sections of the Psion
SIBO C SDK for more information on writing EPOC-16 programs for
the SIBO architecture.
1.2 Supported application development environments
The PsiStack SDK allows programmers to develop TCP/IP applications
using a variety of languages and styles.
1.2.1 C Sockets Library
The SDK supplies the link library PSISTACK.LIB (and associated header
files) which provides the sockets functionality for use in C programs,
using the SIBO C SDK and TopSpeed C Compiler. The asynchronous
functionality is also provided in this library, as are the standard
word-conversion, address conversion and DNS lookup functions. PsiStack also
gives the application writer extensive facilities for control and monitoring of
the TCP/IP stack. These functions are also included in PSISTACK.LIB.
1.2.2 Psion OO Sockets Library
To be announced
1.2.3 OPL Sockets Library
To be announced
1.2.4 Java java.net Package
To be announced
Java on SIBO/EPOC-16 platforms to be provided by the Psion-Java
project.
1.2.5 Forth Sockets Words
To be announced
ANS Forth on SIBO/EPOC-16 platforms to be provided by the Psion-Forth
project.
1.2.6 Other languages
The above libraries are simply stub libraries which communicate
with the PsiStack TCP/IP kernel. The protocol used in the inter-process
communications between client and kernel is documented in the
PsiStack Technical Guide, available from the same place you obtained
this SDK. Using this protocol, it would be possible to add support
for PsiStack to any language which allows access to EPOC-16/PLIB
functions, for example, assembler, forth, etc. The source code
to the C sockets library is available as part of the PsiStack
source package - the functions in that library merely copy their
parameters to a structure, send that structure to the stack kernel,
and return the result.
1.3 SDK contents
The SDK does NOT contain PsiStack itself. A separate 'binaries'
archive is available for this. Refer to the PsiStack Owner's Manual
for details of how (and where) to install the PsiStack kernel
and applications on your Psion.
The SDK contains the following files for installation on the PC-based development system:
PSISTACK.LIB C Sockets link library *.H C Header files INSTSDK.BAT Installation script
Note: The installation script assumes that you installed your SIBO C SDK in the default C:\SIBOSDK directory. If this is NOT the case, edit the INSTSDK.BAT file and change the path as indicated.
After installation, the files in the temporary directory can be safely deleted.
The installation copies the header files to the following locations:
High-level API header files C:\SIBOSDK\INCLUDE\ARPA\TFTP.H C:\SIBOSDK\INCLUDE\NETINET\IN.H C:\SIBOSDK\INCLUDE\SYS\SOCKET.H C:\SIBOSDK\INCLUDE\PATHS.H (obsolete) C:\SIBOSDK\INCLUDE\NETDB.H Low-level API header files C:\SIBOSDK\INCLUDE\PSISTACK\*.H Very Low-level API (Kernel Internal) header files C:\SIBOSDK\INCLUDE\PSISTACK\SYS\*.H API Link Library C:\SIBOSDK\LIB\PSISTACK.LIB
TCP, SOCK_STREAM connections. TCP is not yet finished.
UDP, SOCK_DGRAM connections. UDP is almost finished, but the sockets library calls which support it are not.
Raw sockets. The interface to the IP layer has not yet been decided. The stack's built-in ping program accesses the ICMP layer internally - an interface for this has not yet been 'broken out' so that external programs such as traceroute, nslookup, etc. could be written.
Raw interface sockets. By opening a raw interface socket,
an application can make use of the PsiStack dial-up scripting
language to dial a phone number and negotiate a login procedure.
When the login has succeeded, the receive data appearing at the
serial interface is passed directly to the application, and the
application can send data out. Essentially, it provides straight
serial access plus the dial-up scripting language. If all communications
programs are re-written to use PsiStack in this way, then a single
scripting language can be used - and might become a standard.
Although the Series 3 machines have a built-in comms application,
there is no programmer interface to its scripting language.
1.6 Compatibility with other sockets implementations
The sockets interface as presented attempts to be fully compatible
with the BSD-style sockets implementation found on Linux. Many
of the header files included in this SDK were modified from the
Linux kernel/library source code. (See Acknowledgements)
At the time of writing, Psion have not yet released the SDK for their TCP/IP stack to unregistered developers. This means that the SDK presented here will probably not be compatible with Psion's TCP/IP SDK.
The sockets abstraction can be used for much more than TCP/IP communications - it could be used for NetBIOS, AppleTalk, IrDA, Ethernet, with their respective addressing schemes, etc. However, the PsiStack sockets interface supports communications only in the Internet (PF_INET) domain, using the Internet address family (AF_INET).
A socket is defined an endpoint of a communication path. When
created, a socket does not contain any information about how it
will be used - such as the protocol port numbers or IP addresses
of either the local or remote machines. Before it is used, the
socket must be bound to one or both endpoint addresses
- port numbers and IP addresses.
2.3 Addressing
The general, family/protocol-independent addressing structure
is known as a sockaddr structure, and is defined in <sys\socket.h>
as:
struct sockaddr { unsigned char sa_len; /* Total length */ unsigned short sa_family; /* Address family, AF_xxx */ char sa_data[14]; /* 14 bytes of protocol address */ };
Rather than use this general-purpose addressing structure to specify endpoints, and to aid portability, use the sockaddr_in structure:
struct sockaddr_in { unsigned char sin_len; /* Total length */ unsigned short sin_family; /* Address family, AF_xxx */ unsigned short sin_port; /* Protocol port number */ unsigned long sin_addr; /* IP address */ char sin_zero[8]; };
Each TCP/IP endpoint address comprises a 2-byte sin_family
field that identifies the address type, which must be AF_INET;
a 2-byte port number sin_port; a 4-byte IP address sin_addr.
The rest of the structure is unused for AF_INET addresses.
2.4 Socket types
There are two major styles of communication between endpoints:
connectionless (datagram) and connection-oriented (stream). In
TCP/IP, connectionless communication is achieved using UDP (user
datagram protocol), and connection-oriented communication is achieved
using TCP (transport control protocol).
UDP provides an bidirectional unreliable connectionless delivery service using IP to transport messages between machines. It uses IP to carry messages, and therefore determines the addresses of these machines using their IP addresses, but adds the ability to distinguish between multiple destinations within a given host computer, using protocol port numbers. An application using UDP must accept full responsibility for handling the reliability (or otherwise) of the link, which may suffer from message loss, message duplication, delays, out-of-order delivery, and loss of connection. Datagram transfer preserves record boundaries - datagrams are discrete records.
In contrast, TCP provides a bidirectional reliable, connection-oriented, buffered, unstructured stream-oriented, full duplex delivery service. It too uses IP to carry the data stream, but uses the connection, not the protocol port as its fundamental abstraction; connections are identified by a pair of endpoints. Because of this, a given TCP port number can be shared by multiple connections on the same machine. Before TCP data can be passed, applications at both ends of the connection must agree that the connection should be opened. One end performs a passive open, indicating that it will accept an incoming connection. The TCP/IP stack will allocate a TCP port number for this end of the connection. The other application will then issue an active open to establish the connection. The connection is established and data may pass. When finished, the connection is broken. Stream transfer does not preserve record boundaries.
There are three types of socket:
SOCK_DGRAM, a socket used for the delivery of datagrams using UDP.
SOCK_STREAM, a socket used for the reliable delivery of stream data using TCP.
SOCK_RAW, a socket used for the transmission of raw IP
datagrams. They are used to access the underlying communication
protocols that form the stack kernel - ICMP and DNS are examples
where raw sockets may be used (traceroute and nslookup, for example,
require the use of raw sockets.)
2.5 Structure of the sockets library, and asynchronous sockets functionality
Note: None of the async functions exist yet. Basically, there will only really be an async API. The synchronous API sits atop the asynchronous API, waiting for I/O to complete using p_waitstat(). The BSD sockets library will be yet another translation layer on top of this async/sync I/O layer. The PMI layer will possibly be a set of preprocessor definitions which mutate PMI-like ("s_") calls into our "socket_" calls. I'm guessing on the structure of the PMI API.There are (will be, more like!) four ways of accessing the TCP/IP facilities provided by PsiStack:Sockets code (of any type) is largely unwritten.
Each library function has a synchronous and asynchronous version. With the asynchronous version, the programmer must also supply the address of a status word. The library will initialise this to the EPOC-16 constant E_FILE_PENDING. When the call completes, the stack will change this to some return code (the exact value will depend on the outcome of the function), and will trigger an asynchronous event, by signaling the application's asynchronous request semaphore. Applications typically perform many asynchronous operations, such as queueing timer events, device reads, user interface (keypress) reads, etc. Each of these events has a separate status word. The application then suspends itself until one or more of these events complete, using the p_iowait() PLIB function, or similar. When any of these events complete, the asynchronous request semaphore is signaled by the operating system, the application unblocks, and each event's status word is polled, to determine which events have completed. The completed events are acted upon; new operations may be queued, and the loop continues.
Asynchronous versions of the sockets library functions are shown in the manual pages. Each asynchronous function ends in 'a', and its final parameter is the address of the associated status word. The penultimate parameter is usually a pointer to some data area which is used to store the result of the call. Synchronous versions of the calls store their result in static buffers allocated inside the sockets library - the return value of synchronous calls is known at the time the function returns, and can easily be stored elsewhere at run-time, whereas the asynchronous versions do not complete immediately after they have been called, and so the result indicates whether the message has been passed to the kernel successfully. Therefore, the address of the return value storage area must be given. When the application unblocks, and the sockets call's status word is found to indicate a completion, the result value can be inspected.
For example (from <sys\socket.h>) :
extern struct hostent *gethostbyname(char *name);
extern UINT gethostbynamea(char *name, struct hostent *result, UINT *statword);
The synchronous sockets calls are actually 'convenience routines' that wrap around the asynchronous versions - they perform the necessary blocking while the function completes asynchronously. Applications which queue multiple events - for example receiving timer events or key presses - should always use the asynchronous versions.
The BSD Sockets interface also uses the asynchronous and synchronous
socket_ calls, but presents them to a client program in a BSD-like
manner. e.g. functions return -1 on failure, not a negative error code.
2.6 Creating a socket
Note: All this documentation still to do... sigh...
As an application programmer, you can use the synchronous versions of the sockets interface, and never worry about whether the stack kernel is loaded, whether a dial-up connection is active or not, or know anything about the progress of the dial-up process. Your first sockets call will load the stack, and the first socket opened will cause the stack to dial out. The functions you call will return failure if the stack could not load, or the connection could not be established, but that's all - you won't be able to find out what actually went wrong.
Discovering this information requires your application to use the stack kernel interface to some extent. This allows you to control the kernel with a little more precision. You will be able to load the stack when your application initialises. (If you don't do this asynchronously, your application will block while the stack loads and initialises itself). You will be able to initiate dial-up connections, and receive status updates regarding the state of the connection on startup (opening serial port, resetting modem, dialling out, waiting for dial tone, connected, running script, data-link layer negotiation in progress, interface 'up') and on closedown (data-link layer closedown in progress, running disconnection script, interface 'down', hanging up modem, closing serial port). This enables you to keep your user informed. You will be able to perform on-the-fly configuration of the stack kernel while it is running.
The database is accessed and manipulated by calling routines from the database link library.
7.1 Using the database link library
A linkable library is provided which allows applications to access
and modify this database, by sending requests to the database server.
This section is to be completed when the database implementation is more complete, and the Host Connect Table / Method Table system has been built.
There are more details in the technical guide.
Note: MS Word really mangled my typesetting on this section. I've got to reformat it all in nice HTML_... could take some time...
gethostbyname, gethostbyaddr, sethostent, endhostent, herror - get network host entrySYNOPSIS
DESCRIPTION#include <netdb.h> extern int h_errno; struct hostent *gethostbyname(const char *name); struct hostent *gethostbyaddr(const char *addr, int len, int type); void sethostent(int stayopen); void endhostent(void); void herror(const char *s);
The gethostbyname() function returns a structure of type hostent for the given host name. The current domain and its parents are searched unless name ends in a dot. If name doesn't end in a dot and the environment variable HOSTALIASES is set, the alias file pointed to by HOSTALIASES will first be searched for name.
The gethostbyaddr() function returns a structure of type hostent for the given host address addr of length len and address type type. The only valid address type is currently AF_INET.
The sethostent() function specifies, if stayopen is true (1), that a connected TCP socket should be used for the name server queries and that the connection should remain open during successive queries. Otherwise, name server queries will use UDP datagrams.
The endhostent() function ends the use of a TCP connection for name server queries.
The herror() function prints the error message associated with the current value of h_errno on stderr.
The domain name queries carried out by gethostbyname() and gethostbyaddr() use a combination of any or all of the name server named(8), a broken out line from /etc/hosts, and the Network Information Service (NIS or YP), depending upon the contents of the order line in /etc/host.conf. (See resolv+(8)). The default action is to query named(8), followed by /etc/hosts.
The hostent structure is defined in <netdb.h> as follows:
The members of the hostent structure are:
A zero-terminated array of alternative names for the host.
h_addrtype
The type of address; always AF_INET at present.
h_length
The length of the address in bytes.
h_addr_list
A zero-terminated array of network addresses for the host in network byte order.
h_addr The first address in h_addr_list for backward compatibility.
RETURN VALUE
The gethostbyname() and gethostbyaddr() functions return the hostent structure or a NULL pointer if an error occurs. On error, the h_errno variable holds an error number.
ERRORS
The variable h_errno can have the following values:
HOST_NOT_FOUND
The specified host is unknown.
NO_ADDRESS
The requested name is valid but does not have an IP address.
NO_RECOVERY
A non-recoverable name server error occurred.
TRY_AGAIN
A temporary error occurred on an authoritative name server. Try again later.
FILES
/etc/host.conf resolver configuration file
/etc/hosts host database file
SEE ALSO
resolver(3), hosts(5), hostname(7), resolv+ (8), named(8)
9.1.2 GETNETENT
NAME
getnetent, getnetbyname, getnetbyaddr, setnetent, endnetent - get network entry
SYNOPSIS
#include <netdb.h> struct netent *getnetent(void); struct netent *getnetbyname(const char *name); struct netent *getnetbyaddr(long net, int type); void setnetent(int stayopen); void endnetent(void);
DESCRIPTION
The getnetent() function reads the next line from the file /etc/networks and returns a structure netent containing the broken out fields from the line. The /etc/networks file is opened if necessary.
The getnetbyname() function returns a netent structure for the line from /etc/networks that matches the network name.
The getnetbyaddr() function returns a netent structure for the line that matches the network number net of type type.
The setnetent() function opens and rewinds the /etc/net- works file. If stayopen is true (1), then the file will not be closed between calls to getnetbyname() and getnet- byaddr().
The endservent() function closes /etc/networks.
The netent structure is defined in <netdb.h> as follows:
struct netent { char *n_name; /* official network name */ char **n_aliases; /* alias list */ int n_addrtype; /* net address type */ unsigned long int n_net; /* network number */ }
The members of the netent structure are:
n_name The official name of the network.
n_aliases
A zero terminated list of alternative names for the network.
n_addrtype
The type of the network number; always AF_INET.
n_net The network number in host byte order.
RETURN VALUE
The getnetent(), getnetbyname() and getnetbyaddr() func- tions return the netent structure, or a NULL pointer if an error occurs or the end of the file is reached.
FILES
/etc/networks networks database file
SEE ALSO
getprotoent(3), getservent(3), networks(5)
9.1.3 GETPROTOENT
NAME
getprotoent, getprotobyname, getprotobynumber, setprotoent, endprotoent - get protocol entry
SYNOPSIS
#include <netdb.h> struct protoent *getprotoent(void); struct protoent *getprotobyname(const char *name); struct protoent *getprotobynumber(int proto); void setprotoent(int stayopen); void endprotoent(void);
DESCRIPTION
The getprotoent() function reads the next line from the file /etc/protocols and returns a structure protoent containing the broken out fields from the line. The /etc/protocols file is opened if necessary.
The getprotobyname() function returns a protoent structure for the line from /etc/protocols that matches the protocol name name.
The getprotobynumber() function returns a protoent struc- ture for the line that matches the protocol number number.
The setprotoent() function opens and rewinds the /etc/pro- tocols file. If stayopen is true (1), then the file will not be closed between calls to getprotobyname() or getprotobynumber().
The endprotoent() function closes /etc/protocols.
The protoent structure is defined in <netdb.h> as follows:
struct protoent { char *p_name; /* official protocol name */ char **p_aliases; /* alias list */ int p_proto; /* protocol number */ }
The members of the protoent structure are:
p_name The official name of the protocol.
p_aliases
A zero terminated list of alternative names for the protocol.
p_proto
The protocol number.
RETURN VALUE
The getprotoent(), getprotobyname() and getprotobynumber() functions return the protoent structure, or a NULL pointer if an error occurs or the end of the file is reached.
FILES
/etc/protocols protocol database file
SEE ALSO
getservent(3), getnetent(3), protocols(5)
9.1.4 GETSERVENT
NAME
getservent, getservbyname, getservbyport, setservent, endservent - get service entry
SYNOPSIS
#include <netdb.h> struct servent *getservent(void); struct servent *getservbyname(const char *name, const char *proto); struct servent *getservbyport(int port, const char *proto); void setservent(int stayopen); void endservent(void);
DESCRIPTION
The getservent() function reads the next line from the file /etc/services and returns a structure servent con- taining the broken out fields from the line. The /etc/services file is opened if necessary.
The getservbyname() function returns a servent structure for the line from /etc/services that matches the service name using protocol proto.
The getservbyport() function returns a servent structure for the line that matches the port port using protocol proto.
The setservent() function opens and rewinds the /etc/ser- vices file. If stayopen is true (1), then the file will not be closed between calls to getservbyname() and get- servbyport().
The endservent() function closes /etc/services.
The servent structure is defined in <netdb.h> as follows:
struct servent { char *s_name; /* official service name */ char **s_aliases; /* alias list */ int s_port; /* port number */ char *s_proto; /* protocol to use */ }
The members of the servent structure are:
s_name The official name of the service.
s_aliases
A zero terminated list of alternative names for the service.
s_port The port number for the service given in network byte order.
s_proto The name of the protocol to use with this service.
RETURN VALUE
The getservent(), getservbyname() and getservbyport() functions return the servent structure, or a NULL pointer if an error occurs or the end of the file is reached.
FILES
/etc/services services database file
SEE ALSO
getprotoent(3), getnetent(3), services(5)
9.1.5 GETHOSTID
NAME
gethostid, sethostid - get or set the unique identifier of the current host
SYNOPSIS
#include <unistd.h> long int gethostid(void); int sethostid(long int hostid)
DESCRIPTION
Get or set a unique 32-bit identifier for the current machine.
The 32-bit identifier is intended to be unique among all UNIX systems in existence. This normally resem- bles the Internet address for the local machine, as returned by gethostbyname(3), and thus usually never needs to be set.
The sethostid call is restricted to the superuser.
The hostid argument is stored in the file /etc/hostid.
RETURN VALUES
gethostid returns the 32-bit identifier for the current host as set by sethostid(2).
FILES
/etc/hostid
SEE ALSO
hostid(1), gethostbyname(3)
9.1.6 GETHOSTNAME
NAME
gethostname, sethostname - get/set host name
SYNOPSIS
#include <unistd.h> int gethostname(char *name, size_t len); int sethostname(const char *name, size_t len);
DESCRIPTION
These functions are used to access or to change the host name of the current processor.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
EINVAL len is negative or, for sethostname, len is larger than the maximum allowed size, or, for gethostname on Linux/i386, len is smaller than the actual size.
EPERM For sethostname, the caller was not the superuser.
EFAULT name is an invalid address.
BUGS
Some other implementations of gethostname successfully return len bytes even if name is longer. Linux/Alpha com- plies with this behaviour. Linux/i386, however, returns EINVAL in this case (as of DLL 4.6.27 libraries).
NOTES
Under Linux/Alpha, gethostname is a system call. Under Linux/i386, gethostname is implemented at the library level by calling uname(2).
SEE ALSO
getdomainname(2), setdomainname(2), uname(2)
9.1.7 GETPEERNAME
NAME
getpeername - get name of connected peer
SYNOPSIS
int getpeername(int s, struct sockaddr *name, int *namelen);
DESCRIPTION
Getpeername returns the name of the peer connected to socket s. The namelen parameter should be initialized to indicate the amount of space pointed to by name. On return it contains the actual size of the name returned (in bytes). The name is truncated if the buffer provided is too small.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
EBADF The argument s is not a valid descriptor.
ENOTSOCK
The argument s is a file, not a socket.
ENOTCONN
The socket is not connected.
ENOBUFS Insufficient resources were available in the system to perform the operation.
EFAULT The name parameter points to memory not in a valid part of the process address space.
SEE ALSO
accept(2), bind(2), getsockname(2)
9.2 Socket interface functions
9.2.1 SOCKET
NAME
socket - create an endpoint for communication
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int socket(int domain, int type, int protocol);
DESCRIPTION
Socket creates an endpoint for communication and returns a descriptor.
The domain parameter specifies a communications domain within which communication will take place; this selects the protocol family which should be used. These families are defined in the include file sys/socket.h. The only understood format is AF_INET (ARPA Internet protocols).
The socket has the indicated type, which specifies the semantics of communication. Currently defined types are:
SOCK_STREAM
SOCK_DGRAM
SOCK_RAW
A SOCK_STREAM type provides sequenced, reliable, two-way connection based byte streams. An out-of-band data trans- mission mechanism may be supported. A SOCK_DGRAM socket supports datagrams (connectionless, unreliable messages of a fixed (typically small) maximum length).
SOCK_RAW sockets provide access to internal network protocols and interfaces.
The protocol specifies a particular protocol to be used with the socket. Normally only a single protocol exists to support a particular socket type within a given protocol family. However, it is possible that many protocols may exist, in which case a particular protocol must be specified in this manner. The protocol number to use is particular to the "communication domain" in which communication is to take place; see protocols(5).
Sockets of type SOCK_STREAM are full-duplex byte streams, similar to pipes. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a connect(2) call. Once connected, data may be transferred using read(2) and write(2) calls or some variant of the send(2) and recv(2) calls. When a session has been completed a close(2) may be performed. Out-of-band data may also be transmitted as described in send(2) and received as described in recv(2).
The communications protocols used to implement a SOCK_STREAM insure that data is not lost or duplicated. If a piece of data for which the peer protocol has buffer space cannot be successfully transmitted within a reason- able length of time, then the connection is considered broken and calls will indicate an error with -1 returns and with ETIMEDOUT as the specific code in the global variable errno. The protocols optionally keep sockets warm by forcing transmissions roughly every minute in the absence of other activity. An error is then indicated if no response can be elicited on an otherwise idle connection for a extended period (e.g. 5 minutes). A SIGPIPE signal is raised if a process sends on a broken stream; this causes naive processes, which do not handle the signal, to exit.
SOCK_DGRAM and SOCK_RAW sockets allow sending of datagrams to correspondents named in send(2) calls. Datagrams are generally received with recvfrom(2), which returns the next datagram with its return address.
An fcntl(2) call can be used to specify a process group to receive a SIGURG signal when the out-of-band data arrives. It may also enable non-blocking I/O and asynchronous notification of I/O events via SIGIO.
The operation of sockets is controlled by socket level options. These options are defined in the file sys/socket.h. Setsockopt(2) and getsockopt(2) are used to set and get options, respectively.
RETURN VALUES
A -1 is returned if an error occurs, otherwise the return value is a descriptor referencing the socket.
ERRORS
EPROTONOSUPPORT
The protocol type or the specified protocol is not supported within this domain.
EMFILE The per-process descriptor table is full.
ENFILE The system file table is full.
EACCESS Permission to create a socket of the specified type and/or protocol is denied.
ENOBUFS Insufficient buffer space is available. The socket cannot be created until sufficient resources are freed. HISTORY
The socket function call appeared in BSD 4.2.
SEE ALSO
accept(2), bind(2), connect(2), getprotoent(3), getsockname(2), getsockopt(2), ioctl(2), listen(2), read(2), recv(2), select(2), send(2), shutdown(2), socketpair(2), write(2)
"An Introductory 4.3 BSD Interprocess Communication Tutorial" is reprinted in UNIX Programmer's Supplementary Documents Volume 1
"BSD Interprocess Communication Tutorial" is reprinted
in UNIX Programmer's Supplementary Documents Volume 1
9.2.2 SOCKETPAIR
NAME
socketpair - create a pair of connected sockets
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int socketpair(int d, int type, int protocol, int sv[2]);
DESCRIPTION
The call creates an unnamed pair of connected sockets in the specified domain d, of the specified type, and using the optionally specified protocol. The descriptors used in referencing the new sockets are returned in sv[0] and sv[1]. The two sockets are indistinguishable.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
EMFILE Too many descriptors are in use by this process.
EAFNOSUPPORT
The specified address family is not supported on this machine.
EPROTONOSUPPORT
The specified protocol is not supported on this machine.
EOPNOSUPPORT
The specified protocol does not support creation of socket pairs.
EFAULT The address sv does not specify a valid part of the process address space.
BUGS
This call is currently implemented only for the UNIX domain. [Documenter's note: is this true for Linux?]
SEE ALSO
read(2), write(2), pipe(2)
9.2.3 BIND
NAME
bind - bind a name to a socket
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
DESCRIPTION
bind gives the socket, sockfd, the local address my_addr. my_addr is addrlen bytes long. Traditionally, this is called "assigning a name to a socket" (when a socket is created with socket(2), it exists in a name space (address family) but has no name assigned.)
NOTES
Binding a name in the UNIX domain creates a socket in the file system that must be deleted by the caller when it is no longer needed (using unlink(2)).
The rules used in name binding vary between communication domains.
Consult the manual entries in section 4 for detailed information.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is
set appropriately.
ERRORS
EBADF sockfd is not a valid descriptor.
EINVAL The socket is already bound to an address. This may change in the future: see linux/unix/sock.c for details.
EACCES The address is protected, and the user is not the super-user.
EFAULT my_addr points outside your accessible address space.
ENAMETOOLONG my_addr is too long.
ENOENT The file does not exist.
ENOMEM Insufficient kernel memory was available.
ENOTDIR A component of the path prefix is not a directory.
EACCES Search permission is denied on a component of the path prefix.
ELOOP my_addr contains a circular reference (i.e., via a symbolic link)
SEE ALSO
accept(2),connect(2), listen(2), socket(2), getsockname(2)
9.2.4 CONNECT
NAME
connect - initiate a connection on a socket
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int connect(int sockfd, struct sockaddr *serv_addr, int addrlen );
DESCRIPTION
The parameter sockfd is a socket. If it is of type SOCK_DGRAM, this call specifies the peer with which the socket is to be associated; this address is that to which datagrams are to be sent, and the only address from which datagrams are to be received. If the socket is of type SOCK_STREAM , this call attempts to make a connection to another socket. The other socket is specified by serv_addr, which is an address in the communications space of the socket. Each communications space interprets the serv_addr, parameter in its own way. Generally, stream sockets may successfully connect only once; datagram sock- ets may use connect multiple times to change their association. Datagram sockets may dissolve the association by connecting to an invalid address, such as a null address.
RETURN VALUE
If the connection or binding succeeds, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
See the Linux kernel source code for details.
SEE ALSO
accept(2), bind(2), listen(2), socket(2), getsockname(2)
9.2.5 ACCEPT
NAME
accept - accept a connection on a socket
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int accept(int s, struct sockaddr *addr, int *addrlen);
DESCRIPTION
The argument s is a socket that has been created with socket(2), bound to an address with bind(2), and is lis- tening for connections after a listen(2). The accept argument extracts the first connection request on the queue of pending connections, creates a new socket with the same properties of s and allocates a new file descrip- tor for the socket. If no pending connections are present on the queue, and the socket is not marked as non-block- ing, accept blocks the caller until a connection is pre- sent. If the socket is marked non-blocking and no pending connections are present on the queue, accept returns an error as described below. The accepted socket may not be used to accept more connections. The original socket s remains open.
The argument addr is a result parameter that is filled in with the address of the connecting entity, as known to the communications layer. The exact format of the addr parameter is determined by the domain in which the communication is occurring. The addrlen is a value-result parameter; it should initially contain the amount of space pointed to by addr; on return it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types, currently with SOCK_STREAM.
It is possible to select(2) a socket for the purposes of doing an accept by selecting it for read.
For certain protocols which require an explicit confirmation, such as ISO or DATAKIT, accept can be thought of as merely dequeuing the next connection request and not implying confirmation. Confirmation can be implied by a normal read or write on the new file descriptor, and rejection can be implied by closing the new socket.
One can obtain user connection request data without confirming the connection by issuing a recvmsg(2) call with an msg_iovlen of 0 and a non-zero msg_controllen, or by issuing a getsockopt(2) request. Similarly, one can pro- vide user connection rejection information by issuing a sendmsg(2) call with providing only the control information, or by calling setsockopt(2).
RETURN VALUES
The call returns -1 on error. If it succeeds, it returns a non-negative integer that is a descriptor for the accepted socket.
ERRORS
EBADF The descriptor is invalid.
ENOTSOCK
The descriptor references a file, not a socket.
EOPNOTSUPP
The referenced socket is not of type SOCK_STREAM.
EFAULT The addr parameter is not in a writable part of the user address space.
EWOULDBLOCK
The socket is marked non-blocking and no connections are present to be accepted.
SEE ALSO
bind(2), connect(2), listen(2), select(2), socket(2)
9.2.6 LISTEN
NAME
listen - listen for connections on a socket
SYNOPSIS
#include <sys/socket.h> int listen(int s, int backlog);
DESCRIPTION
To accept connections, a socket is first created with socket(2), a willingness to accept incoming connections and a queue limit for incoming connections are specified with listen, and then the connections are accepted with accept(2). The listen call applies only to sockets of type SOCK_STREAM.
The backlog parameter defines the maximum length the queue of pending connections may grow to. If a connection request arrives with the queue full the client may receive an error with an indication of ECONNREFUSED, or, if the underlying protocol supports retransmission, the request may be ignored so that retries may succeed.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
EBADF The argument s is not a valid descriptor.
ENOTSOCK
The argument s is not a socket.
EOPNOTSUPP
The socket is not of a type that supports the operation listen.
BUGS
If the socket is of type af_inet, and the backlog argument is greater than 128 it is silently truncated to 128. For portable applications don't rely on this value since BSD (and at least some BSD derived systems) limit the backlog to 5.
SEE ALSO
accept(2), connect(2), socket(2)
9.2.7 GETSOCKNAME
NAME
getsockname - get socket name
SYNOPSIS
int getsockname(int s , struct sockaddr * name , int * namelen )
DESCRIPTION
Getsockname returns the current name for the specified socket. The namelen parameter should be initialized to indicate the amount of space pointed to by name. On return it contains the actual size of the name returned (in bytes).
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately. A 0 is returned if the call succeeds, -1 if it fails.
ERRORS
EBADF The argument s is not a valid descriptor.
ENOTSOCK
The argument s is a file, not a socket.
ENOBUFS Insufficient resources were available in the system to perform the operation.
EFAULT The name parameter points to memory not in a valid part of the process address space.
BUGS
Names bound to sockets in the UNIX domain are inaccessible; getsockname returns a zero length name.
SEE ALSO
bind(2), socket(2)
9.2.8 GETSOCKOPT
NAME
getsockopt, setsockopt - get and set options on sockets
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int getsockopt(int s, int level, int optname, void *optval, int *optlen); int setsockopt(int s, int level, int optname, const void *optval, int optlen);
DESCRIPTION
Getsockopt and setsockopt manipulate the options associated with a socket. Options may exist at multiple protocol levels; they are always present at the uppermost socket level.
When manipulating socket options the level at which the option resides and the name of the option must be specified. To manipulate options at the socket level, level is specified as SOL_SOCKET . To manipulate options at any other level the protocol number of the appropriate protocol controlling the option is supplied. For example, to indicate that an option is to be interpreted by the TCP protocol, level should be set to the protocol number of TCP; see getprotoent(3).
The parameters optval and optlen are used to access option values for setsockopt. For getsockopt they identify a buffer in which the value for the requested option(s) are to be returned. For getsockopt, optlen is a value-result parameter, initially containing the size of the buffer pointed to by optval, and modified on return to indicate the actual size of the value returned. If no option value is to be supplied or returned, optval may be NULL.
Optname and any specified options are passed uninterpreted to the appropriate protocol module for interpretation. The include file sys/socket.h contains definitions for socket level options, described below. Options at other protocol levels vary in format and name; consult the appropriate entries in section 4 of the manual.
Most socket-level options utilize an int parameter for optval. For setsockopt, the parameter should be non-zero to enable a boolean option, or zero if the option is to be disabled. SO_LINGER uses a struct linger parameter, defined in sys/socket.h, which specifies the desired state of the option and the linger interval (see below). SO_SNDTIMEO and SO_RCVTIMEO use a struct timeval parame- ter, defined in sys/time.h.
The following options are recognized at the socket level. Except as noted, each may be examined with getsockopt and set with setsockopt .
SO_DEBUG
enables recording of debugging information
SO_REUSEADDR
enables local address reuse
SO_KEEPALIVE
enables keep connections alive
SO_DONTROUTE
enables routing bypass for outgoing messages
SO_LINGER
linger on close if data present
SO_BROADCAST
enables permission to transmit broadcast messages
SO_OOBINLINE
enables reception of out-of-band data in band
SO_SNDBUF
set buffer size for output
SO_RCVBUF
set buffer size for input
SO_SNDLOWAT
set minimum count for output
SO_RCVLOWAT
set minimum count for input
SO_SNDTIMEO
set timeout value for output
SO_RCVTIMEO
set timeout value for input
SO_TYPE
get the type of the socket (get only)
SO_ERROR
get and clear error on the socket (get only)
SO_DEBUG enables debugging in the underlying protocol modules.
SO_REUSEADDR indicates that the rules used in validating addresses supplied in a bind(2) call should allow reuse of local addresses.
SO_KEEPALIVE enables the periodic transmission of messages on a connected socket. Should the connected party fail to respond to these messages, the connection is considered broken and pro- cesses using the socket are notified via a SIGPIPE signal when attempting to send data.
SO_DONTROUTE indicates that outgoing messages should bypass the standard routing facilities. Instead, messages are directed to the appropriate network interface according to the network portion of the destination address.
SO_LINGER controls the action taken when unsent messages are queued on socket and a close(2) is performed. If the socket promises reliable delivery of data and SO_LINGER is set, the system will block the process on the close attempt until it is able to transmit the data or until it decides it is unable to deliver the information (a timeout period, termed the linger interval, is specified in the setsockopt call when SO_LINGER is requested). If SO_LINGER is disabled and a close is issued, the system will process the close in a manner that allows the process to continue as quickly as possible.
SO_BROADCAST requests permission to send broadcast datagrams on the socket. Broadcast was a privileged operation in earlier versions of the system.
With protocols that support out-of-band data, the SO_OOBINLINE option requests that out-of-band data be placed in the normal data input queue as received; it will then be accessible with recv or read calls without the MSG_OOB flag. Some protocols always behave as if this option is set.
SO_SNDBUF and SO_RCVBUF are options to adjust the normal buffer sizes allocated for output and input buffers, respectively. The buffer size may be increased for high-volume connections, or may be decreased to limit the possible backlog of incoming data. The system places an absolute limit on these values.
SO_SNDLOWAT is an option to set the minimum count for out- put operations. Most output operations process all of the data supplied by the call, delivering data to the protocol for transmission and blocking as necessary for flow control. Nonblocking output operations will process as much data as permitted subject to flow control without blocking, but will process no data if flow control does not allow the smaller of the low water mark value or the entire request to be processed. A select(2) operation testing the ability to write to a socket will return true only if the low water mark amount could be processed. The default value for SO_SNDLOWAT is set to a convenient size for network efficiency, often 1024. SO_RCVLOWAT is an option to set the minimum count for input operations. In general, receive calls will block until any (non-zero) amount of data is received, then return with smaller of the amount available or the amount requested. The default value for SO_SNDLOWAT is 1. If SO_SNDLOWAT is set to a larger value, blocking receive calls normally wait until they have received the smaller of the low water mark value or the requested amount. Receive calls may still return less than the low water mark if an error occurs, a signal is caught, or the type of data next in the receive queue is different than that returned.
SO_SNDTIMEO is an option to set a timeout value for output operations. It accepts a struct timeval parameter with the number of seconds and microseconds used to limit waits for output operations to complete. If a send operation has blocked for this much time, it returns with a partial count or with the error EWOULDBLOCK if no data were sent. In the current implementation, this timer is restarted each time additional data are delivered to the protocol, implying that the limit applies to output portions ranging in size from the low water mark to the high water mark for output. SO_RCVTIMEO is an option to set a timeout value for input operations. It accepts a struct timeval parame- ter with the number of seconds and microseconds used to limit waits for input operations to complete. In the current implementation, this timer is restarted each time additional data are received by the protocol, and thus the limit is in effect an inactivity timer. If a receive operation has been blocked for this much time without receiving additional data, it returns with a short count or with the error EWOULDBLOCK if no data were received.
Finally, SO_TYPE and SO_ERROR are options used only with setsockopt. SO_TYPE returns the type of the socket, such as SOCK_STREAM; it is useful for servers that inherit sockets on startup. SO_ERROR returns any pending error on the socket and clears the error status. It may be used to check for asynchronous errors on connected datagram sockets or for other asynchronous errors.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
EBADF The argument s is not a valid descriptor.
ENOTSOCK
The argument s is a file, not a socket.
ENOPROTOOPT
The option is unknown at the level indicated.
EFAULT The address pointed to by optval is not in a valid part of the process address space. For getsockopt, this error may also be returned if optlen is not in a valid part of the process address space.
BUGS
Several of the socket options should be handled at lower levels of the system.
SEE ALSO
ioctl(2), socket(2), getprotoent(3), protocols(5)
9.2.9 SEND
NAME
send, sendto, sendmsg - send a message from a socket
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int send(int s, const void *msg, int len , unsigned int flags); int sendto(int s, const void *msg, int len unsigned int flags, const struct sockaddr *to, int tolen); int sendmsg(int s, const struct msghdr *msg , unsigned int flags);
DESCRIPTION
WARNING: This is a BSD man page. As of Linux 0.99.11, sendmsg was not implemented.
Send, sendto, and sendmsg are used to transmit a message to another socket. Send may be used only when the socket is in a connected state, while sendto and sendmsg may be used at any time.
The address of the target is given by to with tolen speci- fying its size. The length of the message is given by len. If the message is too long to pass atomically through the underlying protocol, the error EMSGSIZE is returned, and the message is not transmitted.
No indication of failure to deliver is implicit in a send. Locally detected errors are indicated by a return value of -1.
If no messages space is available at the socket to hold the message to be transmitted, then send normally blocks, unless the socket has been placed in non-blocking I/O mode. The select(2) call may be used to determine when it is possible to send more data.
The flags parameter may include one or more of the following:
#define MSG_OOB 0x1 /* process out-of-band data */
#define MSG_DONTROUTE 0x4 /* bypass routing, use direct interface */
The flag MSG_OOB is used to send out-of-band data on sockets that support this notion (e.g. SOCK_STREAM); the underlying protocol must also support out-of-band data. MSG_DONTROUTE is usually used only by diagnostic or routing programs.
See recv(2) for a description of the msghdr structure.
RETURN VALUES
The call returns the number of characters sent, or -1 if an error occurred.
ERRORS
EBADF An invalid descriptor was specified.
ENOTSOCK
The argument s is not a socket.
EFAULT An invalid user space address was specified for a parameter.
EMSGSIZE
The socket requires that message be sent atomically, and the size of the message to be sent made this impossible.
EWOULDBLOCK
The socket is marked non-blocking and the requested operation would block.
ENOBUFS The system was unable to allocate an internal buffer. The operation may succeed when buffers become available.
ENOBUFS The output queue for a network interface was full. This generally indicates that the interface has stopped sending, but may be caused by transient congestion.
SEE ALSO
fcntl(2), recv(2), select(2), getsockopt(2), socket(2), write(2)
9.2.10 RECV
NAME
recv, recvfrom, recvmsg - receive a message from a socket
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> int recv(int s, void *buf, int len, unsigned int flags); int recvfrom(int s, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen); int recvmsg(int s, struct msghdr *msg, unsigned int flags);
DESCRIPTION
WARNING: This is a BSD man page. As of Linux 0.99.11, recvmsg was not implemented.
Recvfrom and recvmsg are used to receive messages from a socket, and may be used to receive data on a socket whether or not it is connection-oriented.
If from is non-nil, and the socket is not connection-oriented, the source address of the message is filled in. Fromlen is a value-result parameter, initialized to the size of the buffer associated with from, and modified on return to indicate the actual size of the address stored there.
The recv call is normally used only on a connected socket (see connect(2)) and is identical to recvfrom with a nil from parameter. As it is redundant, it may not be sup- ported in future releases.
All three routines return the length of the message on successful completion. If a message is too long to fit in the supplied buffer, excess bytes may be discarded depend- ing on the type of socket the message is received from (see socket(2)).
If no messages are available at the socket, the receive call waits for a message to arrive, unless the socket is nonblocking (see fcntl(2)) in which case the value -1 is returned and the external variable errno set to EWOULDBLOCK. The receive calls normally return any data avail- able, up to the requested amount, rather than waiting for receipt of the full amount requested; this behavior is affected by the socket-level options SO_RCVLOWAT and SO_RCVTIMEO described in getsockopt(2).
The select(2) call may be used to determine when more data arrive.
The flags argument to a recv call is formed by or'ing one or more of the values:
MSG_OOB process out-of-band data
MSG_PEEK
peek at incoming message
MSG_WAITALL
wait for full request or error
The MSG_OOB flag requests receipt of out-of-band data that would not be received in the normal data stream. Some protocols place expedited data at the head of the normal data queue, and thus this flag cannot be used with such protocols. The MSG_PEEK flag causes the receive operation to return data from the beginning of the receive queue without removing that data from the queue. Thus, a subsequent receive call will return the same data. The MSG_WAITALL flag requests that the operation block until the full request is satisfied. However, the call may still return less data than requested if a signal is caught, an error or disconnect occurs, or the next data to be received is of a different type than that returned.
The recvmsg call uses a msghdr structure to minimize the number of directly supplied parameters. This structure has the following form, as defined in sys/socket.h:
struct msghdr { caddr_t msg_name; /* optional address */ u_int msg_namelen; /* size of address */ struct iovec *msg_iov; /* scatter/gather array */ u_int msg_iovlen; /* # elements in msg_iov */ caddr_t msg_control; /* ancillary data, see below */ u_int msg_controllen; /* ancillary data buffer len */ int msg_flags; /* flags on received message */ };
Here msg_name and msg_namelen specify the destination address if the socket is unconnected; msg_name may be given as a null pointer if no names are desired or required. Msg_iov and msg_iovlen describe scatter gather locations, as discussed in read(2). Msg_control, which has length msg_controllen, points to a buffer for other protocol control related messages or other miscellaneous ancillary data. The messages are of the form:
struct cmsghdr { u_int cmsg_len; /* data byte count, including hdr */ int cmsg_level; /* originating protocol */ int cmsg_type; /* protocol-specific type */ /* followed by u_char cmsg_data[]; */ };
As an example, one could use this to learn of changes in the data-stream in XNS/SPP, or in ISO, to obtain user-connection-request data by requesting a recvmsg with no data buffer provided immediately after an accept call.
Open file descriptors are now passed as ancillary data for AF_UNIX domain sockets, with cmsg_level set to SOL_SOCKET and cmsg_type set to SCM_RIGHTS.
The msg_flags field is set on return according to the message received. MSG_EOR indicates end-of-record; the data returned completed a record (generally used with sockets of type SOCK_SEQPACKET). MSG_TRUNC indicates that the trailing portion of a datagram was discarded because the datagram was larger than the buffer supplied. MSG_CTRUNC indicates that some control data were discarded due to lack of space in the buffer for ancillary data. MSG_OOB is returned to indicate that expedited or out-of-band data were received.
RETURN VALUES
These calls return the number of bytes received, or -1 if an error occurred.
ERRORS
EBADF The argument s is an invalid descriptor.
ENOTCONN
The socket is associated with a connection-oriented protocol and has not been connected (see connect(2) and accept(2)).
ENOTSOCK
The argument s does not refer to a socket.
EWOULDBLOCK
The socket is marked non-blocking, and the receive operation would block, or a receive timeout had been set, and the timeout expired before data were received.
EINTR The receive was interrupted by delivery of a signal before any data were available.
EFAULT The receive buffer pointer(s) point outside the process's address space.
SEE ALSO
fcntl(2), read(2), select(2), getsockopt(2), socket(2)
9.2.11 SHUTDOWN
NAME
shutdown - shut down part of a full-duplex connection
SYNOPSIS
#include <sys/socket.h> int shutdown(int s, int how);
DESCRIPTION
The shutdown call causes all or part of a full-duplex connection on the socket associated with s to be shut down. If how is 0, further receives will be disallowed. If how is 1, further sends will be disallowed. If how is 2, further sends and receives will be disallowed.
RETURN VALUE
On success, zero is returned. On error, -1 is returned, and errno is set appropriately.
ERRORS
EBADF S is not a valid descriptor.
ENOTSOCK
S is a file, not a socket.
ENOTCONN
The specified socket is not connected.
SEE ALSO
connect(2), socket(2)
9.2.12 SELECT
NAME
select - synchronous I/O multiplexing
SYNOPSIS
#include <sys/time.h> #include <sys/types.h> #include <unistd.h> int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); FD_CLR(int fd, fd_set *set); FD_ISSET(int fd, fd_set *set); FD_SET(int fd, fd_set *set); FD_ZERO(fd_set *set);
DESCRIPTION
select waits for a number of file descriptors to change status.
Three independent sets of descriptors are watched. Those listed in readfds will be watched to see if characters become available for reading, those in writefds will be watched to see if it is ok to immediately write on them, and those in exceptfds will be watched for exceptions. On exit, the sets are modified in place to indicate which descriptors actually changed status.
Four macros are provided to manipulate the sets. FD_ZERO will clear a set. FD_SET and FD_CLR add or remove a given descriptor from a set. FD_ISSET tests to see if a descriptor is part of the set; this is useful after select returns.
n is the highest-numbered descriptor in any of the three sets, plus 1.
timeout is an upper bound on the amount of time elapsed before select returns. It may be zero, causing select to return immediately. If the timeout is NULL (no timeout), select can block indefinitely.
RETURN VALUE
On success, select returns the number of descriptors contained in the descriptor sets, which may be zero if the timeout expires before anything interesting happens. On error, -1 is returned, and errno is set appropriately; the sets and timeout become undefined, so do not rely on their contents after an error.
ERRORS
EBADF An invalid file descriptor was given in one of the sets.
EINTR A non blocked signal was caught.
EINVAL n is negative.
ENOMEM select was unable to allocate memory for internal tables.
NOTES
Some code calls select with all three sets empty, n zero, and a non-null timeout as a fairly portable way to sleep with subsecond precision.
On Linux, timeout is modified to reflect the amount of time not slept; most other implementations do not do this. This causes problems both when Linux code which reads timeout is ported to other operating systems, and when code is ported to Linux that reuses a struct timeval for multiple selects in a loop without reinitializing it. Consider timeout to be undefined after select returns.
EXAMPLE
#include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> int main(void) { fd_set rfds; struct timeval tv; int retval; /* Watch stdin (fd 0) to see when it has input. */ FD_ZERO(&rfds); FD_SET(0, &rfds); /* Wait up to five seconds. */ tv.tv_sec = 5; tv.tv_usec = 0; retval = select(1, &rfds, NULL, NULL, &tv); /* Don't rely on the value of tv now! */ if (retval) printf("Data is available now.\n"); /* FD_ISSET(0, &rfds) will be true */ else printf("No data within five seconds.\n"); exit(0); }
SEE ALSO
accept(2), connect(2), read(2), recv(2), send(2), write(2)
9.2.13 CLOSE
NAME
close - close a file descriptor
SYNOPSIS
#include <unistd.h> int close(int fd);
DESCRIPTION
close closes a file descriptor, so that it no longer refers to any file and may be reused.
If fd is the last copy of a particular file descriptor the resources associated with it are freed; for example any locks held are removed and if the descriptor was the last reference to a file which has been removed using unlink the file is deleted.
RETURN VALUE
close returns zero on success, or -1 if an error occurred.
ERRORS
EBADF fd isn't a valid open file descriptor.
NOTES
Not checking the return value of close is a common but nevertheless serious programming error. File system implementations which use techniques as ``write-behind'' to increase performance may lead to write(2) succeeding, although the data has not been written yet. The error status may be reported at a later write operation, but it is guaranteed to be reported on closing the file. Not checking the return value when closing the file may lead to silent loss of data. This can especially be observed with NFS and disk quotas.
SEE ALSO
open(2), fcntl(2), shutdown(2), unlink(2), fclose(3).
9.2.14 READ
NAME
read - read from a file descriptor
SYNOPSIS
#include <sys/types.h> #include <unistd.h> int read(int fd, char *buf, size_t count);
DESCRIPTION
read reads up to count bytes from file descriptor fd into the buffer starting at buf.
RETURN VALUE
On success, the number of bytes read are returned (zero indicates
end of file). On error, -1 is returned, and errno is set appropriately.
ERRORS
EINTR The call was interrupted by a signal before any data was read.
EAGAIN Non-blocking I/O has been selected using O_NON- BLOCK and no data was immediately available for reading. EISDIR fd refers to a directory.
EBADF fd is not a valid file descriptor or is not open for reading.
EINVAL fd is attached to an object which is unsuitable for reading.
EFAULT buf is outside your accessible address space.
Other errors may occur, depending on the object connected to fd.
SEE ALSO
readdir(2), write(2), write(2), fcntl(2), close(2), lseek(2),
select(2), readlink(2), ioctl(2), fread(3).
9.2.15 WRITE
NAME
write - write to a file descriptor
SYNOPSIS
#include <sys/types.h> #include <unistd.h> size_t write(int fd, const char *buf, size_t count);
DESCRIPTION
write writes up to count bytes from file descriptor fd from the buffer starting at buf.
RETURN VALUE
On success, the number of bytes written are returned (zero indicates nothing was written). On error, -1 (or MAXINT, as size_t is unsigned) is returned, and errno is set appropriately.
ERRORS
EBADF fd is not a valid file descriptor or is not open for writing.
EINVAL fd is attached to an object which is unsuitable for writing.
EFAULT buf is outside your accessible address space.
EPIPE fd is connected to a pipe or socket whose reading end is closed. When this happens the writing process will receive a SIGPIPE signal; if it catches, blocks or ignores this the error EPIPE is returned.
EAGAIN Non-blocking I/O has been selected using O_NONBLOCK and there was no room in the pipe or socket connected to fd to write the data immediately.
EINTR The call was interrupted by a signal before any data was written.
ENOSPC The device containing the file referred to by fd has no room for the data.
Other errors may occur, depending on the object connected to fd.
SEE ALSO
open(2), read(2), fcntl(2), close(2), lseek(2), select(2), ioctl(2),
fwrite(3).
9.3 Utility functions
9.3.1 BYTEORDER
NAME
htonl, htons, ntohl, ntohs - convert values between host and network byte order
SYNOPSIS
#include <netinet/in.h> unsigned long int htonl(unsigned long int hostlong); unsigned short int htons(unsigned short int hostshort); unsigned long int ntohl(unsigned long int netlong); unsigned short int ntohs(unsigned short int netshort);
DESCRIPTION
The htonl() function converts the long integer hostlong from host byte order to network byte order. The htons() function converts the short integer hostshort from host byte order to network byte order. The ntohl() function converts the long integer netlong from network byte order to host byte order. The ntohs() function converts the short integer netshort from network byte order to host byte order.
On the i80x86 the host byte order is Least Significant Byte first, whereas the network byte order, as used on the Internet, is Most Significant Byte first.
SEE ALSO
gethostbyname(3), getservent(3)
9.3.2 INET
NAME
inet_addr, inet_network, inet_ntoa, inet_makeaddr, inet_lnaof, inet_netof - Internet address manipulation routines
SYNOPSIS
#include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> unsigned long int inet_addr(const char *cp); unsigned long int inet_network(const char *cp); char *inet_ntoa(struct in_addr in); struct in_addr inet_makeaddr(int net, int host); unsigned long int inet_lnaof(struct in_addr in); unsigned long int inet_netof(struct in_addr in);
DESCRIPTION
The inet_addr() function converts the Internet host
address cp from numbers-and-dots notation into binary data in network byte order. If the input is invalid, -1 is returned.
The inet_network() function extracts the network number in network byte order from the address cp in numbers-and-dots notation. If the input is invalid, -1 is returned.
The inet_ntoa() function converts the Internet host address in given in network byte order to a string in standard numbers-and-dots notation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite.
The inet_makeaddr() function makes an Internet host address in network byte order by combining the network number net with the local address host in network net, both in local host byte order.
The inet_lnaof() function returns the local host address part of the Internet address in. The local host address is returned in local host byte order.
The inet_netof() function returns the network number part of the Internet Address in. The network number is returned in local host byte order.
The structure in_addr as used in inet_ntoa(), inet_makeaddr(), inet_lnoaf() and inet_netof() is defined in netinet/in.h as:
struct in_addr { unsigned long int s_addr; }
Note that on the i80x86 the host byte order is Least Significant Byte first, whereas the network byte order, as used on the Internet, is Most Significant Byte first.
SEE ALSO
gethostbyname(3), getnetent(3), hosts(5), networks(5)
This section will hold a listing of the PsiStack database, with explanations of the entries. Since the database isn't fixed yet, I haven't done this bit.
[Comer 96] "Internetworking with TCP/IP Volume III",
2ed, BSD Sockets with ANSI C
Douglas E. Comer & David L. Stevens