Socket Programming

By Jay Schwartz

Socket communication is a form of virtual circuit that rides on top of TCP/IP. Every machine is called a host. This word can be confusing since it is common to equate host with server. I will try to describe each host as either a client or a server and avoid the word "host" entirely.

Each machine (or host) has an IP address. It is generally expressed in dotted form, which is a number in the form x.x.x.x. The machine may also have a name, but this name is translated into dotted form. (This is the function of a name server.)

As we know, real computers are likely to be doing several functions simultaneously. If more than one function chooses to use the same network connection (LAN card). Then there needs to be a way to share the connection so that messages can be routed to the appropriate application. This is where sockets come in to play. A socket address is a combination of a dotted address (representing a machine) and a port number (16 bit unsigned). Thus, if a user or application knew both the dotted address and the port number, he could communicate directly with the desired application.

Although sockets are bidirectional, every communication involves a client side and a server side. Generally, the server runs continually. Its address and port are well known. The server remains blocked waiting for a connection from a client. The client program can send messages to a server at any time.

One interesting thing about sockets is that client and server can be anywhere. That is, they may will be in the same machine. Or they may be on different machines on the same LAN. Or they may be communicating worldwide via the Internet. Also, sockets are not operating system dependent.

I have worked on two projects that involve socket programming. On the first project my piece runs on OS/2 and communicates with a mainframe. The nature of the communication is such that either machine may decide to send a message to the other at any time. Therefore, both machines are set up as socket servers, each with its own port number.

The second project is on AIX, a version of Unix. In this case the client and server are both running Unix and usually are running on the same machine. My job is to provide a server and a library that an application program links to in order to communicate with this server. Messages flow mainly from the client to the server, and even when data flows from the server to the client, the communication is still initiated by the client. Furthermore, the data returned is limited to only 4 bytes.

Bear in mind that, when a connection established between a client and server, other clients will not get through to the server and will block waiting for detection. Therefore, it is common to keep conversations quite short. In both cases in which I am involved, the conversation consists of a message from the client to the server, followed by a very short acknowledgment from the server back to the client. At that point the connection ends, making the server available to other clients.

The tools required for socket programming include a library of socket functions (which may be static or dynamic), several header files, and the appropriate documentation. Needless to say, I am only aware of a C language interface, although others may exist too.

I have referred to both a dotted address and a port. The actual socket number is neither of these. It is an internal number assigned by the system and is analogous to a file handle.

The functions can be grouped as follows:
 * Initialization.
 * Connection.
 * Communication.
 * Utility.

The utility functions are used mainly for lineup and data conversion. For example if you know a host name, there is a function to convert that into the dotted address. In fact, you need another utility to convert the dotted address into a pure 32 bit number. A client always knows the address of the server since it is specifically sending to that address. A server, on the other hand, will not know the address of the client unless it uses another utility that specifically returns the client address.

The communication functions consist mainly of send and recv. The standard send and recv are blocking functions. This means that once called they do not return until the message is sent or received. In a single-threaded program blocking functions can be a nuisance. There are nonblocking equivalent functions available as well. I find that with multiple threads, having the send or recv wait for completion the most direct and efficient approach.

For the server the function accept puts up the antenna and waits until a connection request arrives. Again, this function blocks waiting for a connection. For the client the function connect establishes a communication link with the server. Connect, oddly enough, does not block. It returns immediately with a success or failure value. I generally put the connect call in a loop trying several hundred times to connect with a server before giving up.

The initialization functions are just that; a few calls that must be made once only in the program to get the socket interface working.

Revised: 2001 Feb 18