This section describes the Unix BSD networking API for IP as in WR Stevens ``Unix Network Programming.'' This is a message based API. It looks at a simple program using TCP and also using UDP. Some other elements of this style of programming are mentioned.

Some foreign sites

Here is just a few of the machines that offer Internet services around the world

Byte ordering

To handle byte ordering for non-standard size integers there are conversion functions

Address conversion

These functions convert to and from the ``dotted'' addresses as in to 32 bit integer addresses: #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> unsigned long inet_addr(char *ptr) char * inet_ntoa(struct in_addr in) (The structure in_addr has only one field which is the 32 bit IP address.)


The address of an IP service given is using a structure #include <netinet/in.h> struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; } Example: The finger service (port 79) on machine is given by struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(79); addr.sin_addr.s_addr = inet_addr("");


A socket is a data structure maintained by a BSD-Unix system to handle network connections.

A socket is created using the call ``socket''. It returns an integer that is like a file descriptor: it is an index into a table and ``reads'' and ``writes'' to the network use this ``socket file descriptor''.

#include <sys/types.h> #include <sys/socket.h> int socket(int family, int type, int protocol); Here ``family'' will be AF_INET for IP communications, ``protocol'' will be zero, and ``type'' will depend on whether TCP or UDP is used.

Two processes wishing to communicate over a network create a socket each. These are similar to two ends of a pipe - but the actual pipe does not yet exist.

Connection oriented (TCP)

One process (server) makes its socket known to the system using ``bind''. This will allow other sockets to find it.

It then ``listens'' on this socket to ``accept'' any incoming messages.

The other process (client) establishes a network connection to it, and then the two exchange messages.

As many messages as needed may be sent along this channel, in either direction.

TCP time client

Each machine runs a TCP server on port 13 that returns in readable form the time on that particular machine. All that a client has to do is to connect to that machine and then read the time from that machine.

Example: If the program is compiled to ``tcptime'', find the time in various places by

TCP time server

The real time server can only be started by the system supervisor (usually at boot time) as the time port is reserved. To run the following code yourself, change the time port to say 2013. int main(int argc, char *argv[]) { int sockfd; int nread; struct sockaddr_in serv_addr, client_addr; time_t t; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror(NULL); exit(2); } serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = inet_addr(INADDR_ANY); serv_addr.sin_port = htons(TIME_PORT); listen(sockfd, 5); for (;;;) { client_sockfd = accept(sockfd, &client_addr, &len); time(&t); sprintf(buf, "%s", asctime(localtime(t))); len = strlen(buf) + 1; write(1, buf, len); close(client_sockfd); } }

Connectionless (UDP)

In a connectionless protocol both sockets have to make their existence known to the system using ``bind''. This is because each message is treated separately, so the client has to find the server each time it sends a message and vice versa.

When bind is called it binds to a new port - it cannot bind to one already in use. If you specify the port as zero the system gives you a currently unused port.

Because of this extra task on each message send, the processes do not use read/write but recvfrom/sendto. These functions take as parameters the socket to write to, and the address of the service on the remote machine.

Time client (UDP)

The UDP time server requires a datagram to be sent to it. It ignores the contents of the message but uses the return address to send back a datagram containing the time.

Socket controls

Sockets are treated by the O/S as devices and so there are a variety of device driver controls that can be used (see later). For example, the command ``fcntl'' can be used to make a socket non-blocking, and ``select'' can be used to test if a socket (device) has input or output pending.

In addition, ``getsockopt'' and ``setsockopt'' can be used for more specific socket control:

If a read or write does not return, it should timeout. What should the time limit be? On your own machine or on your local network it should be in milliseconds. To Melbourne in seconds, whereas to Scandinavia it should probably be minutes.

Timeout algorithms should adjust the time according to the curent trip time in some manner. They can be implemented using timer signals.

This page is, copyright Jan Newmarch.
It is maintained by Jan Newmarch.
Last modified: 16 October, 1995