Download the Postscript or Word 6.0 version.
Berkeley Sockets
Study and use of Berkeley sockets in network programming.
December 7th, 1997

Contents
1. Berkeley Sockets 2. Socket System Calls 3. Byte Ordering Routines
4. Address Conversion Routines
5. Advanced Socket System Calls 6. Reserved Ports

1. Berkeley Sockets

1.1 Introduction

    1. The network program should know what role it is playing, client or server.
    2. The connection can be of two types, connection-oriented or connection-less.
    3. A network application must know the names of its peer processes to verify that those processes have to authority to request services.
    4. There are a lot of parameters required for a network connection like protocol, local address, local process, foreign address and foreign process.
    5. Support for multiple protocols must be provided e.g. TCP/IP, XNS, etc.

1.2 UNIX Domain Protocols

Sockets in the Unix domain can only be used to communicate with processes in the same Unix system. There are both connection-less and connection-oriented protocols. Both are considered reliable as both exist within the kernel and are not transmitted across communication mediums. The only difference is that the connection-oriented protocol provides flow control while the connection-less does not. The Unix domain protocols provide a feature that is not currently provided by any other protocol family. This is the ability to pass access rights from one process to another e.g. passing of file descriptors. The 5 tuple for this protocol is slightly different.
    1. The protocol is same as before PF_UNIX.
    2. The local and foreign address are zero as they are in the same system.
    3. The local and foreign processes are specified as pathnames.
The system creates some files as specified in the pathname. These are not regular files and cannot be opened by normal system calls. The call stat reports them as S_IFSOCK type.

1.3 Socket Addresses

The socket system call requires a pointer to a socket address structure. The structure is defined in <sys/socket.h> as:
 
struct sockaddr {
        u_short sa_family; // Address family: AF_XXX value
        char sa_data[14];  // Upto 14 bytes of protocol specific address
};

The contents of the 14 bytes of protocol specific address are interpreted according to the type of address.

For the internet family it is defined in <netinet/in.h> as:
 
struct in_addr {
        u_long s_addr;              // 32 bit netid/hostid
};

struct sockaddr_in {
        short sin_family;           // AF_INET
        u_short sin_port;           // 16-bit port number
        struct in_addr sin_addr;    // 32 bit netid/host id defined above
        char sin_zero[8];           // Unused
};

For the Xerox NS family it is defined in <sys/ns.h> as :
 
union ns_host {
    u_char c_host[6];           // Host id address as 6 bytes
    u_short s_host[3];          // Hostid address as three 16-bit shorts
};

union ns_net {
    u_char c_net[4];            // Netid as 4 bytes
    u_short s_net[2];           // Netid as two 16-bit shorts
};

struct ns_addr {                // Combined 12 byte XNS address
    union ns_net x_net;         // 4 byte netid
    union ns_host x_host;       // 6 byte hostid
    u_short x_port;             // 2 byte port
};

struct sockaddr_ns {
    u_short sns_family;         // AF_NS
    struct ns_addr sns_addr;    // 12 byte XNS address
    char sns_zero[2];           // Unused
};

For the Unix domain it is defined in <sys/un.h> as :
 
struct sockaddr_un {
    short sun_family;   // AF_UNIX
    char sun_path[108]; // pathname
};

The system calls have to take a struct sockaddr type structure. So before passing the protocol specific structure it must be typecasted. e.g.
 
struct sockaddr_in serv_addr;
connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

2. Socket System Calls

2.1. Socket()

         
        EACCES Permission to create a socket of the specified type and/or protocol is denied.
        EMFILE The peer-process descriptor table is full.
        ENOMEM Insufficient user memory is available.
        ENOSR There were insufficient STREAMS resources available to complete the operation.
        EPROTONOSUPPORT The protocol type or the specified protocol is not supported within this domain.
    In the 5 tuple association, this system call defines the protocol value. Before using the connection, we must specify the rest of the four values.

2.2. Socketpair()

This call has been implemented for the Unix domain only. It returns a pair of socket descriptors and is similar to the pipe system call. The sockets returned by this system call are bi-directional and are called Unix stream pipes.

Syntax:
 
int socketpair(
    int family,         // Family of protocol
    int type,           // Type of connection
    int protocol,       // Type of protocol
    int sockvec[2]);    // Array to store the socket descriptors

The family is PF_UNIX.

The valid types are:

    1. SOCK_STREAM
    2. SOCK_DGRAM
Since this call is limited for the Unix domain, we do not have any defined protocols so it is always passed as zero. The third parameter is as array of two integers which store the two unnamed and connected socket descriptors on a successful return.

The function returns 0 on success and -1 on error. The errno values are:

EAFNOSUPPORT The specified address family is not supported on this machine.
EMFILE Too many descriptors are in use by this process.
ENOMEM There was insufficient user memory for the operation to complete.
ENOSR There were insufficient STREAMS resources for the operation to complete.
EOPNOSUPPORT The specified protocol does not support creation of socket pairs.
EPROTONOSUPPORT The specified protocol is not supported on this machine.

2.3. Bind()

2.4. Connect()

2.5. Listen()

2.6. Accept()

An actual connection from some client is awaited for by having the server execute this call.

Syntax:
 
int accept(
    int sockfd,            // Socket descriptor
    struct sockaddr *peer, // Address of peer to connect
    int *addrlen);         // Size of address structure

This call takes the first connection request from the queue and creates another socket with the same properties as sockfd. If there are no pending requests, this call blocks.

This function returns:

The new socket descriptor returned by this call completes the 5 tuple.

2.7. Send(), Sendto(), Recv() and Recvfrom()

2.8. Close()

The normal Unix close system call is used for closing a socket.

Syntax:
 
int close(int sockfd);

If the socket being closed is associated with a protocol that promises reliable delivery, the system must ensure that any data within the kernel that still has to be transmitted or acknowledged, is sent.

3. Byte Ordering Routines
     
    FUNCTION DESCRIPTION
    htonl() Convert host to network, long integer
    htons() Convert host to network, short integer
    ntohl() Convert network to host, long integer
    ntohs() Convert network to host, short integer

    Implicit to these functions are that a short integer occupies 16 bits and a long integer occupies 32 bits.

4. Address Conversion Routines
5. Advanced Socket System Calls

5.1 Readv() and Writev()

5.2 Recvmsg() and Sendmsg()

5.3 Getpeername()

5.4 Getsockname()

5.5 Shutdown()

6. Reserved Ports
There are two ways for a process to have a port assigned to it
    1. The process can itself specify the port number.
    2. The process can leave it to the system to assign it any available port.
The system call rresvport is used by a process for assigning a port.

Syntax:
 
int rresvport( int *aport );

The port scenario is shown below:

  Internet XNS
Reserved Ports 1-1023 1-2999
Ports automatically assigned by the system 1024-5000 3000-65535
Ports assigned by rresvport 512-1023 NA
This function checks the value of aport passed to it and assigns any port available equal to or below the value till 512. If successful it creates a socket, binds it to the port and returns the value of the socket descriptor. Otherwise it returns -1 and sets the value of errno to EAGAIN.   1