Connection establishment is usually asymmetric, with one process acting as the client and the other as the server. The server binds a socket to a well-known address associated with the service and blocks on its socket for a connect request. An unrelated process can then connect to the server. The client requests services from the server by initiating a connection to the server's socket. On the client side, the connect(3SOCKET) call initiates a connection. In the Internet family, this might appear as:
struct sockaddr_in6 server; ... connect(s, (struct sockaddr *)&server, sizeof server);
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. See "Address Binding". This is the usual way that local addresses are bound to a socket on the client side.
To receive a client's connection, a server must perform two steps after binding its socket. The first is to indicate how many connection requests can be queued. The second step is to accept a connection:
struct sockaddr_in6 from; ... listen(s, 5); /* Allow queue of 5 connections */ fromlen = sizeof(from); newsock = accept(s, (struct sockaddr *) &from, &fromlen);
The socket handle s is the socket bound to the address to which the connection request is sent. The second parameter of listen(3SOCKET) specifies the maximum number of outstanding connections that might be queued. from is a structure that is filled with the address of the client. A NULL pointer might be passed. fromlen is the length of the structure. (In the UNIX family, from is declared a struct sockaddr_un.)
A server cannot indicate that it accepts connections only from specific addresses. The server can check the from address returned by accept(3SOCKET) and close a connection with an unacceptable client. A server can accept connections on more than one socket, or avoid blocking on the accept call. These techniques are presented in "Advanced Topics".