Sockets

Type of connection:

Network Address

197.124.10.1

Usage:
#include <arpa/inet.h>
 in_addr_t inet_addr(const char *ip_address);
inet_addr takes an IP address in the form of a string like "1 .2 .3 .4" and returns the internet address in the appropriate type. If the call fails because the IP address string is not in the correct format, the return value will be -1.

Port Number

As well as knowing which machine to access, there must also be a way for the client program to connect to the correct server process. To this end a server process sits and listens for connections on a specified port number. Therefore a client process will ask for a connection to a particl1lar machine and a specific port. To continue the previous postal analogy this would be the equivalent of putting the flat or room number as well as the address on the envelope. Some numbers are well-known port numbers and are understood, by conventi(jn, to offer a particular service, for example ftp or rlogin. These numbers are laid down in the file /etc/services. In general, a port number less than 1024 is reserved for UNIX system processes. Anything above can be used for user processes.

Socket Interface

A socket for network communication has the form
#include <netinet/in.h>.
struct sockaddr-in{
sa_family_t       sin_family; /* internet address family */
in_port_t           sin_port; /* port number */
struct in_ addr  sin_addr; /* holds the IP address */
unsigned             char sin_zero[8]; /* filling */
} ;

Creation of a transportation end point

Usage:
#include <syslsocket.h>
int socket(int domain, int type, int protocol);
domain tells the call where the socket is to be used. For example AF_INET specifies the internet domain for networking. Another domain, which may be of interest to the reader, is AF_UNIX, which is used if the processes are on the same machine.

The type of the socket to be created specifies whether it is to be used in a connection or connectionless mode. SOCK_STREAM specifies a connection oriented link, SOCK_DGRAM a connectionless link. The final parameter, protocol, specifies which protocol should be used by this socket. This will normally be set to 0, in which case, by default, a SOCK_STREAM socket wiIl use TCP and a SOCK_DGRAM socket will use UDP-both standard UNIX protocols. The socket system call normally returns a non-negative integer which is the socket file descriptor, which enables sockets to be treated using the familiar UNIX file model.

Binding

The bind system call associates the true network address of a machine with a socket identifier .

Usage:

#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *address,size_t add_len);
The first parameter, sockfd, is the socket file descriptor originally retnrned by the socket system call. The second parameter is here specified as a pointer to a generic socket structure. However, because we are sending information across the network in our example, we will actually provide the address of the relevant struct sockaddr_in which contains the addressing information for our server. The final parameter holds the size of the actual socket structure used. If the bind call is successful then it returns 0. On error, the bind call returns -1, which may happen if a socket already exists for the address. The errno will then contain EADDRINUSE.

Listening

After binding and before any client system can connect to the newly created server endpoint, the server must set itself up to wait for connections. It does this with listen.

Usage:

#include <sys/socket.h>
int listen(int sockfd, int queue-size);
The sockfd parameter is as above. The server can queue up to queue-size incoming connection requests.

Accepting

When the server receives a connect request from a client it has to create an entirely new socket to handle the specific communication. The first socket is used only to establish communication. Creation of the second socket is done using accept.

Usage:

#include <sysltypes.h>
#include <syslsocket.h>
int accept(int sockfd, struct sockaddr *address,size-t *add_len);
The accept system call is passed the listening socket descriptor returned from the original socket system call. On completion, the return value is the new socket id to be used for the communication. The address parameter is filled out with the information about the client. However, because this is a connection oriented communication the server very rarely needs to know the address of the client, and therefore address can be replaced with NULL. If address is not NULL then the variable pointed to by add_len should initially contain the length of the address structure described by address. On the return of the accept call, *add_len will hold the number of bytes actually copied.

Connecting in the client

To ask for a connection to a server process and machine the client uses the connect system call.

Usage:

#include <sys/types.h>
#include <sys/socket.h>
int connect(int csockfd, const struct sockaddr *address,size_t add_len);

The first parameter, csockfd, is the file descriptor for the associated client socket. This has no relationship to the socket id on the server. The address parameter is a pointer to the stucture containing the address of the server and, again, add-len is the length of the specific address structure being used.

Sending and receiving data

If all has gone well a circuit between client and server can now be established. As the sockets are set up to be of type SOCK_STREAM both the client and server will have a (different) file descriptor which can be used for either reading or writing. In most circumstances the read and write system calls can be used in the normal way. However, there are two new system calls which can be used if extra options need to be set about the way the data will be sent across the network. send and recv are as simple to use as read and wri te. In fact, if their fourth argument is set to O they behave identically.

Usage:

#include <sys/types.h>
#include <sys/socket.h>
size_t recv(int sockfd, void *buffer, size_t length,int flags);
size_t send(int sockfd, const void *buffer, size_t length,int flags);

The recv call specifies the file descriptor to read the data from, the buffer into which the data should be put, and the length of the buffer. As with read, recv returns the amount of data read. The flags parameter affects the way in which the data can be received. The possible values are:

MSG_PEEK: The process can look at the data without actually receivingit.

MSG_OOB: Normal data is bypassed and the process only receives out of band data, for example, an interrupt signal.

IMSG_WAITALL: The recv call will only return when the full amount of data is available.

send behaves just like write if the flags parameter is set to 0. It sends the message contained in buffer to sockfd, the local socket. The length parameter specifies the length of buffer. As with recv the flags parameter affects the way that messages are sent. The possible values are:

MSG-OOB: Send 'out of band' data.

MSG-DONTROUTE: The message will be sent ignoring any routing conditions of the underlying protocol. Normally this means that the message will be sent via the most direct route rather than the quickest (the quickest could be more circuitous depending on the current load of the network).

Example

tcpclient.c is a program which connects to another program tcpserver.c running at a given TCP address. The client reads lower case letters from the keyboard and sends them to the server which converts them to upper case letters and sends them back to the client.

Connectionless Sending and receiving data

Usage:

size_t recvfrom(int sockfd, void *message, size_t length, int flags, 
                struct sockaddr *send_addr, size_t *add_len);
size_t sendto(int sockfd, const void *message, size_t length, int flags, 
              const struct sockaddr *dest_addr, size_t dest_len);
The recvfrom call works in exactly the same way as recv if send_addr is set to NULL. The message pointer is the buffer into which the received message will be placed and length is the number of bytes to be read into message. The flags parameter takes identical values to those in the recv call. The last two parameters are those which help with the connectionless form of communication. The send_addr structure will be filled with the address information of the machine which sent the message. This means that the receiving process can send a reply if it so wishes. The final parameter is a pointer to a size_t integer which, on completion of the call, will be filled out with the length of the address.

The sendto call is the opposite of recvfrom. This time the dest_addr parameter specifies the address of the peer for the message to be sent to, and dest_len specifies the length of the address.

Example

udpclient.c is a program which connects to another program udpserver.c running at a given TCP address. The client reads lower case letters from the keyboard and sends them to the server which converts them to upper case letters and sends them back to the client.

Other Man Pages

See also:

man 7 ip
man 7 tcp
man 7 udp
man 7 unix