Network Programming

Sockets

Sockets are a protocol independent method of creating a connection between processes. Sockets can be either Socket are characterized by their domain, type and transport protocol. Common domains are: Common types are: Each socket has one or more protocols. Ex:

Connection based communication

Server performs the following actions Client performs the following actions

Connectionless communication

Communication is symmetric (peer-to-peer)

Sockets API

socket

#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain, int type, int protocol)

Returns a file descriptor (called a socket ID) if successful, -1 otherwise.

The type arguments are

Protocol is usually zero, so the.

Note that the socket returns a socket descriptor which is the same as a file descriptor (-1 if failure).

bind

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sid, struct sockaddr *addrPtr, int len)

Where For the internet family:
struct sockaddr_in {
   short          sin_family; // = AF_INET
   u_short        sin_port;   // is a port number
   struct in_addr sin_addr;   // an IP address
}

For unix sockets (only works between processes on the same machine)
struct sockaddr {
   short          sin_family; // = AF_UNIX
   char           sin_port[]; // is a port number
}

listen

#include <sys/types.h>
#include <sys/socket.h>

int listen(int sid, int size)

Where size it the number of pending connection requests allowed (typically limited by Unix kernels to 5).

accept

#include <sys/types.h>
#include <sys/socket.h>

int accept(int sid, struct sockaddr *addrPtr, int *lenPtr)

Returns the address of client connecting to socket

if lenPtr or addrPtr equal zero, no address structure is returned

lenPtr is the maximum size of address structure that can be called, returns the actual value.

send

#include <sys/types.h>
#include <sys/socket.h>


int send(int sid, const char *bufferPtr, int len, int flags)

flag is either

recv

#include <sys/types.h>
#include <sys/socket.h>

int recv(int sid, char *bufferPtr, int len, int flags)

flags can be either

shutdown

#include <sys/types.h>
#include <sys/socket.h>

int shutdown(int sid, int how)

Disables sending (how=1 or how=2) or receiving (how=0 or how=2).

Client calls

connect

#include <sys/types.h>
#include <sys/socket.h>

int connect(int sid, struct sockaddr *addrPtr, int len)

Connectionless protocols

sendto

#include <sys/types.h>
#include <sys/socket.h>

int sendto(int sid, const char *bufferPtr, int len, int flag,
           struct sockaddr *addrPtr, int len)

recvfrom

#include <sys/types.h>
#include <sys/socket.h>

int recvfrom(int sid, const char *bufferPtr, int len, int flag,
           struct sockaddr *addrPtr, int *lenPtr)

Auxiliary functions

Gethostbyname

#include <netdb.h>

struct hostent *gethostbyname(const char *hostname)

Translates a DNS name into a hostent.

The hostent stucture is as follows:

struct hostent {
    char  *h_name;     // official (canonical) name of the host
    char **h_aliases;  // null terminated array of alternative hostnames
    int    h_addrtype; // host address type AF_INET or AF_INET6
    int    h_length;   // 4 or 16 bytes
    char **h_addr_list;// IPv4 or IPv6 list of addresses
}

Error is return through h_error which can be:

Gethostname

#include <unistd.h>

int gethostname(char *hostname, size_t nameLength)

Returns -1 on failure, 0 on success.

MAXHOSTNAMELEN is defined in <sys/param.h>.

Network byte ordering

Network ordering in big endian. (Sparc is big endian, Intel is little endian).

htons

Host to network byte order for shorts (16 bit)
uint_16t htons(uint_16t v);

htonl

Host to network byte order for long (32 bit)
uint_32t htonl(uint_32t v);

ntohs

Network to host byte order for long (16 bit)
uint_16t ntohs(uint_16t v);

ntohl

Network to host byte order for long (32 bit)
uint_32t ntohl(uint_32t v);

IP address strings to 32 bit number

In what follows, 'p' stands for presentation.

inet_pton

#include <arpa/inet.h>

int inet_pton(int family, const char *strPtr, void *addrPtr);

returns 1 if OK, 0 if presentation error, -1 error

Where family is either AF_INET or AF_INET6.

The strPtr is the ip address as a dotted string.

Finally, addrPtr points to either the 32 bit result (AF_INET) or 128 bit result (AF_INET6).

inet_ntop

#include <arpa/inet.h>

int inet_ntop(int family, const char *addrPtr, char *strPtr, size_t len);

returns 1 if OK, 0 if presentation error, -1 error

Where family is either AF_INET or AF_INET6.

The strPtr is the return ip address as a dotted string.

Finally, addrPtr points to either the 32 bit (AF_INET) or 128 bit (AF_INET6).

Length is the size of destination.

Example

TCP/IP Server

Without error checking.
int listenFd, connectFd;
struct sockaddr_in serverAddr;

listenFd = socket(AF_INET, SOCK_STREAM, 0); // get a tcp/ip socket

bzero(&serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); // any iternet interface
                                                // on this server.
serverAddr.sin_port = htons(13);

bind(listenFd, (struct sockaddr_in *) &serverAddr, sizeof(serverAddr));

listen(listenFd, 5);

for ( ; ; ) {
    connectFd = accept(listenFd, (struct sockaddr_in *) NULL, NULL);
       // .. read and write operations on connectFd ..
    shutdown(connectFd, 2);
    close(connectFd);
}

Note that the above is an iterative server, which means that it serves one connection at a time.

To build a concurrent server, a fork is performed after the accept. The child process closes listenFd, and communicates using connectFd. The parent process closses connectFd, and then loops back to the accept to wait for another connection request.

TCP/IP Client code

int sockFd;
struct sockaddr_in serverAddr;

sockFd = socket(AF_INET, SOCK_STREAM, 0); // get a tcp/ip socket

bzero(&serverAddr, sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
inet_pton(AF_INET, serverName, serverAddr.sin_addr); // host IP #
serverAddr.sin_port = htons(13);

connect(sockFd, (struct sockaddr_in *) serverAddr, sizeof(serverAddr));
       // .. read and write operations on sockFd ..
shutdown(sockFd, 2);
close(sockFd);