Protocol Independence
sockaddr_in, AF_INET, sin_family etc. all refer to IPv4. Thus, the below program is dependent on IPv4. To make it work under IPv6, we can change them to sockaddr_in6, AF_INET6, sin6_family etc. Now the program will be protocol-dependent on IPv6. To make the program totally protocol-independent, we use a function - getaddrinfo() which is called by tcpconnect.
Server side programming
Creating a TCP socket
struct sockaddr_in servaddr;
listenfd = socket ( AF_INET, SOCK_STREAM, 0 ) ;
Bind server's well-known port to socket
bzeros ( &servaddr, sizeof (servaddr ) ) ;
servaddr.sin_family = AF_INET ;
servaddr.sin_addr.s_addr = htonl ( INADDR_ANY ) ;
servaddr.sin_port = htons (13 ) ;
bind ( listenfd , ( struct sockaddr * ) &servaddr , sizeof ( srvaddr ) ) ;
The server's well known port ( 13 ) is bound to the socket using the bind function.
The IP address is specified as INADDR_ANY so that the server can accept a client connection on any interface, in case the server host has many interfaces ( IP addresses ) .
Convert Socket to Listening Socket
listen ( listenfd , backlog );
The listen function converts a socket to listening socket. Now, our listenfd socket is fully prepared as a listening descriptor. On listenfd, incoming connections frm clients will be accepted by the kernel.
backlog is just a constant and defines the maximum number of client connections that can be queued by the kernel for this listening descriptor (listenfd).
Note : The server we use in our program is an iterative server, as it iterates through each client one by one and the kernel queues them up. We can create a concurrent server by using fork() function of Unix to create a child process for each incoming client. There are methods as well including threads, or preforking a certain minimum of children when the server starts.
Accept Client Connection and Send Reply
while ( 1 )
{
connfd = accept ( listenfd , (struct sockaddr * ) NULL , NULL ) ;
snprintf ( buff, sizeof ( buff ) , " Hello " ) ;
write ( connfd , buff , strlen ( buff ) ) ;
}
The server process is put to sleep in accept() function, where it waits for incoming client requests. A TCP connection uses 3 way handshake to establish connection. connfd is the descriptor returned by accept() which is now used for further communication. Every new client means a new descriptor is returned every time.
Terminate connection
close ( connfd ) ;
This closes the connection between the server and client and TCP connection termination process begins.