Developing applications over TCP/IP using Internet sockets

Internet address binding

Binding addresses to sockets in the Internet domain can be fairly complex. Communicating processes are bound by an ``association'', shich is composed of local and foreign addresses, and local and foreign ports. Port numbers are allocated out of separate spaces, one for each system and one for each domain on that system. Associations are always unique. That is, there may never be duplicate <protocol, local address, local port, foreign address, foreign port> tuples.

The bind system call allows a process to specify half of an association,

   <local address, local port>
while the connect and accept primitives are used to complete a socket's association. This method has several potential problems. Creating the association in two steps can generate accidental violations of the association uniqueness rule. In addition, user programs may not always know the proper values to use for the local address and local port because a host may reside on multiple networks and the set of allocated port numbers is not directly accessible to a user.

To simplify local address binding, the concept of a ``wildcard'' address has been provided. When an address is specified as INADDR_ANY (a manifest constant defined in netinet/in.h), the system interprets the address as ``any valid address.'' For example, to bind a specific port number to a socket, but leave the local address unspecified, see ``Using a wildcard address''.

Using a wildcard address

#include <sys/types.h>
#include <netinet/in.h>
/* ... */
struct sockaddr_in sin;
/* ... */
s = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = MYPORT;
bind(s, (struct sockaddr *) &sin, sizeof (sin));
Sockets with wildcarded local addresses may receive messages directed to the specified port number and addressed to any of the possible addresses assigned to a host. For example, if a host is on networks 46 and 10 and a socket is bound as above, then when an accept call is performed, the process will be able to accept connection requests which arrive either from network 46 or network 10. If a server process wished to only allow hosts on a given network to connect to it, it would bind the address of the host on the appropriate network.

Similarly, in the Internet domain a local port may be left unspecified (specified as zero), in which case the system will select an appropriate port number for it:

   sin.sin_addr.s_addr = MYADDRESS;

sin.sin_port = 0; bind(s, (struct sockaddr *) &sin, sizeof (sin));

The system selects the port number based on two criteria. The first is that Internet ports numbered 0 through 1023 are reserved for privileged users (that is, root). The second is that the port number is not currently bound to some other socket. The remote shell server finds a free Internet port number in the privileged range by using code like that shown in ``Using a wildcard port number''.

Using a wildcard port number

struct sockaddr_in sin;
/* ... */
lport = IPPORT_RESERVED - 1;
sin.sin_addr.s_addr = INADDR_ANY;
/* ... */
for (;;) {
        sin.sin_port = htons((u_short)lport);
        if (bind(s, (struct sockaddr *) &sin, sizeof (sin)) >= 0)
        if (errno != EADDRINUSE && errno != EADDRNOTAVAIL) {
        if (lport == IPPORT_RESERVED/2) {
                fprintf(stderr, "socket: All ports in use\n");
The restriction on allocating ports was done to allow processes executing in a secure environment to perform authentication based on the originating address and port number.

In certain cases the algorithm used by the system in selecting port numbers is unsuitable for an application. This is because associations are created in a two step process. For example, the Internet file transfer protocol, ftp, 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 port number to a socket if a previous data connection's socket still existed. To override the default port selection algorithm, an option call must be performed prior to address binding:

   setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)0, 0);
   bind(s, (struct sockaddr *) &sin, sizeof (sin));
This call may bind local addresses which are already in use. This does not violate the uniqueness requirement, because the system still checks at connect time to be sure any other sockets with the same local address and port do not have the same foreign address and port. (If an association already exists, the call returns the error EADDRINUSE.)

When a host is on multiple networks, the system binds local addresses somewhat haphazardly. Logically, one would expect the system to bind the local address associated with the network through which a peer was communicating. For instance, if the local host is connected to networks 46 and 10 and the foreign host is on network 32, and traffic from network 32 is arriving via network 10, the local address to be bound would be the host's address on network 10, not network 46.

This, unfortunately, is not always the case. The local address bound may appear to be chosen at random. This property of local address binding will normally be invisible to users unless the foreign host does not understand how to reach the address selected. For example, if network 46 were unknown to the host on network 32, and the local address were bound to that located on network 46, then even though a route between the two hosts existed through network 10, a connection would fail.

Next topic: A typical TCP/IP process
Previous topic: Pseudo terminals (Internet domain)

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003