System Interface Guide

Sockets

Sockets provide point-to-point, two-way communication between two processes. Sockets are very versatile and are a basic component of interprocess and intersystem communication. A socket is an endpoint of communication to which a name can be bound. It has a type and one or more associated processes.

Socket Address Spaces

Sockets exist in communication domains. A socket domain is an abstraction that provides an addressing structure and a set of protocols. Sockets connect only with sockets in the same domain. Twenty three socket domains are identified (see <sys/socket.h>), of which only the UNIX and Internet domains are normally used in Solaris 7 and compatible operating environments.

Sockets can be used to communicate between processes on a single system, like other forms of IPC. The UNIX domain (AF_UNIX) provides a socket address space on a single system. UNIX domain sockets are named with UNIX paths.

Sockets can also be used to communicate between processes on different systems. The socket address space between connected systems is called the Internet domain (AF_INET). Internet domain communication uses the TCP/IP internet protocol suite.

Socket Types

Socket types define the communication properties visible to the application. Processes communicate only between sockets of the same type. There are five types of socket.

Socket Creation and Naming

socket(3N) is called to create a socket in the specified domain and of the specified type. If a protocol is not specified, the system defaults to a protocol that supports the specified socket type. The socket handle (a descriptor) is returned.

A remote process has no way to identify a socket until an address is bound to it. Communicating processes connect through addresses. In the UNIX domain, a connection is usually composed of one or two path names. In the Internet domain, a connection is composed of local and remote addresses and local and remote ports. In most domains, connections must be unique.

bind(3N) is called to bind a path or internet address to a socket. There are three different ways to call bind(3N), depending on the domain of the socket. For UNIX domain sockets with paths containing 14, or fewer characters, you can


#include <sys/socket.h>
 ...
 	bind (sd, (struct sockaddr *) &addr, length);

If the path of a UNIX domain socket requires more characters, use


#include <sys/un.h>
 ...
 	bind (sd, (struct sockaddr *) &addr, length);

And for Internet domain sockets, use


#include <netinet/in.h>
 ...
 	bind (sd, (struct sockaddr *) &addr, length);

In the UNIX domain, binding a name creates a named socket in the file system. Use unlink(2) or rm(1) to remove the socket.

Connecting Stream Sockets

Connecting sockets is usually not symmetric. One process usually acts as a server and the other process is the client. The server binds its socket to a previously agreed path or address. It then blocks on the socket. For a SOCK_STREAM socket, the server calls listen(3N), which specifies how many connection requests can be queued.

A client initiates a connection to the server's socket by a call to connect(3N). A UNIX domain call appears:


struct sockaddr_un server;
 ...
 	connect (sd, (struct sockaddr_un *)&server, length);

while an Internet domain call is:


struct sockaddr_in;
 ...
 	connect (sd, (struct sockaddr_in *)&server, length);

If the client's socket is unbound at the time of the connect call, the system automatically selects and binds a name to the socket.

For a SOCK_STREAM socket, the server calls accept(3N) to complete the connection. accept(3N) returns a new socket descriptor which is valid only for the particular connection. A server can have multiple SOCK_STREAM connections active at one time.

Stream Data Transfer and Closing

There are several functions to send and receive data from a SOCK_STREAM socket. These are write(2), read(2), send(3N), and recv(3N). send(3N) and recv(3N) are very similar to read(2) and write(2), but have some additional operational flags.

A SOCK_STREAM socket is discarded by calling close(2).

Datagram sockets

A datagram socket does not require that a connection be established. Each message carries the destination address. If a particular local address is needed, a call to bind(3N) must precede any data transfer. Data is sent through calls to sendto(3N) or sendmsg(3N) (see send(3N)). The sendto(3N) call is like a send(3N) call with the destination address also specified.

To receive datagram socket messages, call recvfrom(3N)or recvmsg(3N) (see recv(3N)). While recv(3N) requires one buffer for the arriving data, recvfrom(3N) requires two buffers, one for the incoming message and another to receive the source address.

Datagram sockets can also use connect(3N) to connect the socket to a specified destination socket. When this is done, send(3N) and recv(3N) are used to send and receive data.

accept(3N) and listen(3N) are not used with datagram sockets.

Socket Options

Sockets have a number of options that can be fetched with getsockopt(3N) and set with setsockopt(3N). These functions can be used at the native socket level (level = SOL_SOCKET), in which case the socket option name must be specified. To manipulate options at any other level the protocol number of the desired protocol controlling the option of interest must be specified (see getprotoent(3N)).