Programming Interfaces Guide

Address Binding

For addressing, TCP and UDP use a 4-tuple of:

TCP requires these 4-tuples to be unique. UDP does not. User programs do not always know proper values to use for the local address and local port, because a host can reside on multiple networks. The set of allocated port numbers is not directly accessible to a user. To avoid these problems, leave parts of the address unspecified and let the system assign the parts appropriately when needed. Various portions of these tuples can be specified by various parts of the sockets API:

bind(3SOCKET)

Local address or local port or both

connect(3SOCKET)

Foreign address and foreign port

A call to accept(3SOCKET) retrieves connection information from a foreign client. This causes the local address and port to be specified to the system even though the caller of accept(3SOCKET) did not specify anything. The foreign address and foreign port are returned.

A call to listen(3SOCKET) can cause a local port to be chosen. If no explicit bind(3SOCKET) has been done to assign local information, listen(3SOCKET) assigns an ephemeral port number.

A service that resides at a particular port can bind(3SOCKET) to that port. Such a service can leave the local address unspecified if the service does not require local address information. The local address is set to in6addr_any, a variable with a constant value in <netinet/in.h>. If the local port does not need to be fixed, a call to listen(3SOCKET) causes a port to be chosen. Specifying an address of in6addr_any or a port number of 0 is known as “wildcarding.” For AF_INET, INADDR_ANY is used in place of in6addr_any.

The wildcard address simplifies local address binding in the Internet family. The following sample code binds a specific port number that was returned by a call to getaddrinfo(3SOCKET) to a socket and leaves the local address unspecified:

#include <sys/types.h>
#include <netinet/in.h>
...
    struct addrinfo		*aip;
...
    if (bind(sock, aip->ai_addr, aip->ai_addrlen) == -1) {
        perror("bind");
        (void) close(sock);
        return (-1);
    }
		

Each network interface on a host typically has a unique IP address. Sockets with wildcard local addresses can receive messages that are directed to the specified port number. Messages that are sent to any of the possible addresses that are assigned to a host are also received by sockets with wildcard local addresses. To allow only hosts on a specific network to connect to the server, a server binds the address of the interface on the appropriate network.

Similarly, a local port number can be left unspecified, in which case the system selects a port number. For example, to bind a specific local address to a socket, but to leave the local port number unspecified, you could use bind as follows:

bzero (&sin, sizeof (sin));
(void) inet_pton (AF_INET6, ":ffff:127.0.0.1", sin.sin6_addr.s6_addr);
sin.sin6_family = AF_INET6;
sin.sin6_port = htons(0);
bind(s, (struct sockaddr *) &sin, sizeof sin);

The system uses two criteria to select the local port number:

The port number and IP address of the client are found through either accept(3SOCKET) or getpeername(3SOCKET).

In certain cases, the algorithm used by the system to select port numbers is unsuitable for an application due to the two-step creation process for associations. For example, the Internet file transfer protocol specifies that data connections must always originate from the same local port. However, duplicate associations are avoided by connecting to different foreign ports. In this situation, the system would disallow binding the same local address and local port number to a socket if a previous data connection's socket still existed.

To override the default port selection algorithm, you must perform an option call before address binding:

 ...
int on = 1;
...
setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof on);
bind(s, (struct sockaddr *) &sin, sizeof sin);

With this call, local addresses already in use can be bound. This binding does not violate the uniqueness requirement. The system still verifies at connect time that any other sockets with the same local address and local port do not have the same foreign address and foreign port. If the association already exists, the error EADDRINUSE is returned.