Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Unit 1

Download as pdf or txt
Download as pdf or txt
You are on page 1of 39

UNIT 1 ELEMENTARY TCP SOCKETS

Introduction to Socket Programming – Overview of TCP/IP Protocols – Introduction to


Sockets – Socket address Structures – Byte ordering functions – Address conversion
functions – Elementary TCP sockets – socket, connect, bind, listen, accept, read, write,
close functions – Iterative Server – Concurrent server.
1. Introduction to Socket Programming
Network programming involves writing programs that communicate with other programs
across a computer network.
One program is called the client and the other the server.
Network programs are written using an Application Program Interface or API.
There are two types of APIs for network programming,
i. Sockets
ii. XTI (X/ Open Transport Interface)
Most network applications can be divided into two pieces: a client & server.
Communication Link

Fig: Network application: client and server


Networking protocols are used for communication between client application and the server
application.
Web clients and servers communicate using the TCP protocol. TCP, in turn, uses the IP
protocol, and IP communicates with a data link layer of some form.
A server can handle single or multiple clients at a time.
The server executes first and waits to receive the request from the client.
The client executes next and sends the first packet to the server.
After the initial contact, either the client or server is capable of sending and receiving data.
The client and server communicate using an application protocol; the transport layers
communicate using TCP, and so on.
The actual flow of information between the client and server goes down the protocol stack on
one side, across the network, and up the protocol stack on the other side.
The client and server are user processes, while the TCP and IP protocols are normally part of
the protocol stack within the kernel.

Fig: Client and server on the same Ethernet communicating using TCP
In the above fig, the client and server communicate through the single LAN.
In the following fig, we show the client and server on different LANs, with both LANs
connected to WAN using routers.
Routers are the building blocks of WANs. The largest WAN today is the Internet.
2. Overview of TCP/IP Protocol
TCP/IP protocol suite has 5 layers. They are Application, Transport, Network, Data link and
Physical layer.
Most client server applications use either TCP / UDP.
These two protocols inturn use the network layer protocol IP. It may be IP version4 or IP
version6.
It is possible to use IPv4 or IPv6 directly bypassing the transport layer.
UDP is a simple, unreliable, datagram protocol, while TCP is reliable, byte stream protocol.
In the below diagram, right most 4 applications are using IPv6 and next five applications use
IPv4.

The leftmost application, tcpdump, communicates directly with the datalink using either the
BSD packet filter (BPF) or the datalink provider interface (DLPI).
Mark the dashed line below the nine applications on the right as the API, which is normally
sockets or XTI. The interface to either BPF or DLPI does not use sockets or XTI.
In fig, the traceroute program uses two sockets: one for IP and another for ICMP.
IPv4 Internet Protocol version 4. It denote as IP. It uses 32-bit addresses. It provides packet
delivery service for TCP, UDP, SCTP, ICMP, and IGMP.
IPv6 Internet Protocol version 6. It uses 128 bits address. It provides packet delivery service
for TCP, UDP, SCTP, and ICMPv6.
TCP Transmission Control Protocol. It is a connection-oriented protocol that provides a
reliable, full-duplex byte stream to its users. TCP sockets are an example of stream sockets. It
provides the facilities like acknowledgments, timeouts, and retransmissions. Most Internet
application programs use TCP. TCP can use either IPv4 or IPv6.
UDP User Datagram Protocol. It is a connectionless protocol, and UDP sockets are an
example of datagram sockets. There is no guarantee for the delivery of UDP datagrams. It
can use either IPv4 or IPv6.
ICMP Internet Control Message Protocol. It handles error and control information between
routers and hosts. These messages are generated and processed by the TCP/IP networking
software. We show the ping and traceroute programs use ICMP.
IGMP Internet Group Management Protocol. It is used with multicasting, which is optional
with IPv4.
ARP Address Resolution Protocol. ARP maps an IPv4 address into a hardware address
(such as an Ethernet address). ARP is normally used on broadcast networks such as Ethernet,
token ring, and FDDI.
RARP Reverse Address Resolution Protocol. It maps a hardware address into an IPv4
address.
ICMPv6 Internet Control Message Protocol version 6. It combines the functionality of
ICMPv4, IGMP, and ARP.
BPF BSD ( Berkeley Software Distribution) packet filter. This interface provides access to
the datalink layer.
DLPI Datalink provider interface. This interface provides access to the datalink layer.
TCP Connection Establishment and Termination
Three-Way handshake
The following scenario occurs when a TCP connection is established:
1. The server must be prepared to accept an incoming connection. This is normally done by
calling socket, bind, and listen and is called a passive open.
2. The client issues an active open by calling connect. This causes the client TCP to send a
"synchronize" (SYN) segment, it tells the server the client's initial sequence number for
the data that the client will send on the connection. Normally, there is no data sent with
the SYN; it just contains an IP header, a TCP header, and possible TCP options.
3. The server must acknowledge (ACK) the client's SYN and the server must also send its
own SYN containing the initial sequence number for the data that the server will send on
the connection. The server sends its SYN and the ACK of the client's SYN in a single
segment.
4. The client must acknowledge the server's SYN.
The minimum number of packets required for this exchange is three; hence, this is called
TCP's three-way handshake.
Two computers on a network establish a connection using some kind of networking tools
is called handshake.
Figure 2.2. TCP three-way handshake.

We show the client's initial sequence number as J and the server's initial sequence
number as K. The acknowledgment number in the ACK of each SYN is the initial sequence
number plus one.
TCP Options
Each SYN can contain TCP options. Commonly used options are
i. MSS option
The Maximum Segment Size (MSS) is set when TCP connection established.
MSS option can only appear in a SYN segment.
If one end does not receive an MSS option from other end a default 536 byte is assumed.
ii. Window scale option.
TCP always tells its peer exactly how many bytes of data it is willing to accept from the
peer. This is called the advertised window.
The maximum window size is 65,535.
TCP can able to change the window size during the connection establishment.
It never changes the window size during communication.
iii. Timestamp option. This option is needed for high-speed connections to prevent possible
data corruption caused by old, delayed, or duplicated segments.
TCP Connection Termination
TCP takes three segments to establish a connection; it takes four to terminate a connection.
1. One application calls close first, and we say that this end performs the active close. This
end's TCP sends a FIN segment, which means it is finished sending data.
2. The other end that receives the FIN performs the passive close. The received FIN is
acknowledged by TCP. The receipt of the FIN is also passed to the application as an end-of-
file, since the receipt of the FIN means the application will not receive any additional data on
the connection.
3. Sometime later, the application that received the end-of-file will close its socket. This causes
its TCP to send a FIN.
4. The TCP on the system that receives this final FIN acknowledges the FIN.
Since a FIN and an ACK are required in each direction, four segments are normally required. We
use the qualifier "normally" because in some scenarios, the FIN in step 1 is sent with data.
Figure 2.3. Packets exchanged when a TCP connection is closed.

Between Steps 2 and 3 it is possible for data to flow from the end doing the passive close
to the end doing the active close. This is called a half-close.
TCP State Transition Diagram
The operation of TCP with regard to connection establishment and connection
termination can be specified with a state transition diagram.
There are 11 different states defined for a connection and the rules of TCP say the transitions
from one state to another, based on the current state and the segment received in that state.
For example, if an application performs an active open in the CLOSED state, TCP sends a
SYN and the new state is SYN_SENT.

Indicate normal transitions for client


------ Indicate normal transitions for server
appl: Indicate state transitions taken when application issues operation
recv: Indicate state transitions taken when segment received
send: Indicate what is sent for this transition.
If TCP next receives a SYN with an ACK, it sends an ACK and the new state is
ESTABLISHED. This final state is where most data transfer occurs.
The two arrows leading from the ESTABLISHED state deal with the termination of a
connection.
If an application calls close before receiving a FIN (an active close), the transition is to the
FIN_WAIT_1 state.
But if an application receives a FIN while in the ESTABLISHED state (a passive close), the
transition is to the CLOSE_WAIT state.
We denote the normal client transitions with a darker solid line and the normal server
transitions with a darker dashed line.
Simultaneous open - when both ends send SYNs at about the same time and the SYNs cross
in the network
Simultaneous close - when both ends send FINs at the same time.
Watching the Packets
The following fig. shows the actual packet exchange that takes place for a complete TCP
connection: the connection establishment, data transfer, and connection termination.
For example, the client announces an MSS of 1460 and the server announces an MSS of
1024. It is OK for the MSS to be different in each direction.
Once the connection is established, the client forms a request and sends it to the server.
This request fits into a single TCP segment (i.e., less than 1,024 bytes given the server's
announced MSS). The server processes the request and sends a reply, and the reply fits in a
single segment (less than 1460 in this example). We show both data segments as bolder arrows.
The acknowledgment of the client's request is sent with the server's reply. This is called
piggybacking.
If the entire purpose of this connection was to send a one-segment request and receive a
one-segment reply, there would be eight segments of overhead involved when using TCP. If
UDP was used instead, only two packets would be exchanged: the request and the reply.
Fig:Packet exchange for TCP connection.

.
3. Introduction to Socket
Socket is an abstract identifier used by TCP/IP based protocols. It is an end point for
communication.
When there is a need for any resource from the network, the application programs request the
operating system to create a socket.
The system returns a small integer (socket descriptor) that the application program uses to
refer newly created socket.
Socket allows us to exchange information between processes on the same machine or across
a network.
The port number concatenated with the IP address form a socket.
Most application use TCP and UDP for performing a series of operation on that socket.
The operations that can be performed on a socket include control operations (associating a
port number with socket, accepting a connection, destroying the socket) data transfer
operation (read, write) and status operation (finding IP address associated with socket).
Some basic socket system calls are
socket ( ) – To create a new socket and return its descriptor.
bind ( ) – To associate a socket with a port and address.
listen ( ) – To establish queue for connection request.
accept ( ) – To accept a connection request.
connect ( ) – To initiate a connection to remote host.
read ( ) – To read data from a socket descriptor.
write( ) – To write data to a socket descriptor.
close( ) – To close a socket descriptor.
A socket type is uniquely determined by a triple <domain, type, protocol>.
Possible domains are AF_INET (Internet domain version 4), AF_INET6 (Internet domain
version 6), UNIX domain AF_UNIX and AF_LOCAL.
AF_LOCAL – set up socket connection between two process on same host.
The possible socket types are Stream socket (SOCK_STREAM), Datagram socket
(SOCK_DGRAM) and Raw socket (SOCK_RAW).
Stream Socket
These sockets are error free. Sending items are reached at the destination in the same order as
they send.
They use TCP and hence the connection is established between sockets and then the data
transfer occurs.
Datagram Socket
These sockets use UDP. There is no need to open connection in case of datagram sockets.
Raw Socket
They skip the transport layer completely.
If protocol is 0, all packets go to the socket. If protocol is specified, then only the packets
with that protocol are received.
In TCP/IP model interface 1 refers to the interface of Stream socket, interface 2 refers to the
interface of Datagram socket, and interface 3 refers to the interface of Raw socket.

! "

Fig: Location of Socket API in the Communication model.


In the above fig. Socket API are located in between application layer and transport and
network layer. It allows applications to interact with transport or network layer of
communication model.
4. Socket Address Structures
Structure is a data type that is an aggregate, that is, it contains other data types, which are
grouped together into a single user defined type. Structures are used in socket programming to
hold information about the address.
Most socket functions require a pointer to a socket address structure as an argument. Each
supported protocol suite defines its own socket address structure. The names of these structures
begin with sockaddr_ and end with a unique suffix for each protocol suite.
IPv4 Socket Address Structure
An IPv4 socket address structure, commonly called an "Internet socket address
structure," is named sockaddr_in and is defined by including the <netinet/in.h> header.
struct in_addr
{
in_addr_t s_addr; /* 32-bit IPv4 address */
/* network byte ordered */
};
struct sockaddr_in
{
uint8_t sin_len; /* length of structure (16) */
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* 16-bit TCP or UDP port number */
/* network byte ordered */
struct in_addr sin_addr; /* 32-bit IPv4 address */
/* network byte ordered */
char sin_zero[8]; /* unused */
};
sockaddr_in is a parallel structure to deal with struct sockaddr for IPv4 addresses.
sin_port contains the port number and must be in Network byte order.
sin_family corresponds to sa_family and contains the type of address family (AF_INET for
IPv4) and must be in Network byte order.
sin_addr represents Internet address (IPv4).
sin_zero member is unused, but we always set to all zero using bzero( ) or memset( )
functions.
Datatype Description Header
int8_t signed 8-bit integer <sys/types.h>
uint8_t unsigned 8-bit integer <sys/types.h>
int16_t signed 16-bit integer <sys/types.h>
uint16_t Signed 16-bit integer <sys/types.h>
int32_t Signed 32-bit integer <sys/types.h>
uint32_t unsigned 32-bit integer <sys/types.h>
sa_family_t Address family of socket address structure <sys/socket.h>
socklen_t Length of socket address structure, normally uint32_t <sys/socket.h>
in_addr_in IPv4 address, normally uint32_t <netinet/in.h>
in_port_t TCP or UDP port, normally uint16_t <netinet/in.h>

Both the IPv4 address and the TCP or UDP port number are always stored in the structure in
network byte order.
Socket address structures are used only on a given host: the structure itself is not
communicated between different hosts although certain fields (IP address and port) are used
for communication.
Generic Socket Address Structure
A socket address structures is always passed by reference when passed as an argument to
any socket functions. void * is the generic pointer type.
The generic socket address structure: sockaddr.
struct sockaddr
{
uint8_t sa_len;
sa_family_t sa_family; /* address family: AF_xxx value */
char sa_data[14]; /* protocol-specific address */
};
The socket functions are then defined as taking a pointer to the generic socket address structure,
as shown here in the function prototype for the bind function:
int bind(int, struct sockaddr *, socklen_t);
This requires that any calls to these functions must cast the pointer to the protocol-specific socket
address structure to be a pointer to a generic socket address structure. For example,
struct sockaddr_in serv; /* IPv4 socket address structure */
/* fill in serv{} */
bind(sockfd, (struct sockaddr *) &serv, sizeof(serv));
From an application programmer's point of view, the only use of these generic socket address
structures is to cast pointers to protocol-specific structures.
IPv6 Socket address Structure
The IPv6 socket address is defined by including the <netinet/in.h> header
IPv6 socket address structure: sockaddr_in6.
struct in6_addr
{
uint8_t s6_addr[16]; /* 128-bit IPv6 address */
/* network byte ordered */
};
#define SIN6_LEN /* required for compile-time tests */
struct sockaddr_in6
{
uint8_t sin6_len; /* length of this struct (28) */
sa_family_t sin6_family; /* AF_INET6 */
in_port_t sin6_port; /* transport layer port# */
/* network byte ordered */
uint32_t sin6_flowinfo; /* priority, flow label */
/* Network byte order*/
struct in6_addr sin6_addr; /* IPv6 address */
/* network byte ordered */
};
The SIN6_LEN constant must be defined if the system supports the length member for
socket address structures.
The IPv6 family is AF_INET6, whereas the IPv4 family is AF_INET.
The members in this structure are ordered so that if the sockaddr_in6 structure is 64-bit
aligned, so is the 128-bit sin6_addr member.
The sin6_flowinfo member is divided into three fields:
The low-order 24 bits are the flow label
the next 4 bits are the priority,
The next 4 bits are reserved
Comparison of Socket Address Structure
The socket address structures all contain a one-byte length field, that the family field also
occupies one byte.
Two of the socket address structures are fixed-length, while the Unix domain structure and
the datalink structure are variable-length.
To handle variable-length structures, whenever we pass a pointer to a socket address
structure as an argument to one of the socket functions, we pass its length as another
argument.
The sockaddr_un structure itself is not variable-length, but the amount of information—the
pathname within the structure—is variable-length.
5. Byte ordering functions

A16-bit integer that is made up of 2 bytes. There are two ways to store the two bytes in
memory: with the low-order byte at the starting address, known as little-endian byte order, or
with the high-order byte at the starting address, known as big-endian byte order.

Fig: Little-endian byte order and big-endian byte order for a 16-bit integer.

In this fig. we show increasing memory addresses going from right to left in the top, and
from left to right in the bottom. There is no standard between these two byte orderings and we
encounter systems that use both formats. We refer to the byte ordering used by a given system as
the host byte order.
Program to determine host byte order.
#include "unp.h"
int main(int argc, char **argv)
{
union
{
short s;
char c[sizeof(short)];
} un;
un.s = 0x0102;
printf("%s: ", CPU_VENDOR_OS);
if (sizeof(short) == 2)
{
if (un.c[0] == 1 && un.c[1] == 2)
printf("big-endian\n");
else if (un.c[0] == 2 && un.c[1] == 1)
printf("little-endian\n");
else
printf("unknown\n");
}
else
printf("sizeof(short) = %d\n", sizeof(short));
exit(0);
}
We store the 2 byte value 0x0102 into the short integer and then look at the two
consecutive bytes c[0] and c[1] to determine the byte order. The string CPU_VENDOR_OS
identifies the CPU type, vendor, and operating system release.
We must deal with these byte ordering differences as network programmers because
networking protocols must specify a network byte order. For example, in a TCP segment, there
is a 16-bit port number and a 32-bit IPv4 address. The sending protocol stack and the receiving
protocol stack must agree on the order in which the bytes of these multibyte fields will be
transmitted. The Internet protocols use big-endian byte ordering for these multibyte integers.
In theory, an implementation could store the fields in a socket address structure in host
byte order and then convert to and from the network byte order when moving the fields to and
from the protocol headers. We use the following four functions to convert between these two
byte orders.
#include <netinet/in.h>
Both return: value in network byte order
uint16_t htons(uint16_t host16bitvalue) ;
uint32_t htonl(uint32_t host32bitvalue) ;
Both return: value in host byte order
uint16_t ntohs(uint16_t net16bitvalue) ;
uint32_t ntohl(uint32_t net32bitvalue) ;
In the names of these functions, h stands for host, n stands for network, s stands for short, and l
stands for long.
6. Address Conversion functions
inet_aton, inet_addr, and int_ntoa Functions
inet_aton, inet_ntoa, and inet_addr convert an IPv4 address from a dotted-decimal string
(e.g., "206.168.112.96") to its 32-bit network byte ordered binary value.
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
Returns: 1 if string was valid, 0 on error
in_addr_t inet_addr(const char *strptr);
Returns: 32-bit binary network byte ordered IPv4 address; INADDR_NONE if error
char *inet_ntoa(struct in_addr inaddr);
Returns: pointer to dotted-decimal string
inet_aton, converts the C character string pointed to by strptr into its 32-bit binary network
byte ordered value, which is stored through the pointer addrptr. If successful, 1 is returned;
otherwise, 0 is returned.
The inet_addr does the same conversion, returning the 32-bit binary network byte ordered
value as the return value.
The all 232 possible binary values are valid IP addresses (0.0.0.0 through 255.255.255.255),
but the function returns the constant INADDR_NONE (typically 32 one-bits) on an error.
This means the dotted-decimal string 255.255.255.255 (the IPv4 limited broadcast address)
cannot be handled by this function since its binary value appears to indicate failure of the
function.
The inet_ntoa function converts a 32-bit binary network byte ordered IPv4 address into its
corresponding dotted-decimal string.
Functions that take actual structures as arguments are rare. It is more common to pass a
pointer to the structure.
inet_pton and inet_ntop Functions
These two functions are new with IPv6 and work with both IPv4 and IPv6 addresses.
The letters "p" and "n" stand for presentation and numeric.
The presentation format for an address is often an ASCII string and the numeric format is
the binary value that goes into a socket address structure.
#include <arpa/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);
Returns: 1 if OK, 0 if input not a valid presentation format, -1 on error
const char *inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
Returns: pointer to result if OK, NULL on error
The family argument for both functions is either AF_INET or AF_INET6.
If family is not supported, both functions return an error with errno set to EAFNOSUPPORT.
The first function tries to convert the string pointed to by strptr, storing the binary result
through the pointer addrptr.
If successful, the return value is 1. If the input string is not a valid presentation format for the
specified family, 0 is returned.
The inet_ntop does the reverse conversion, from numeric (addrptr) to presentation (strptr).
The len argument is the size of the destination, to prevent the function from overflowing the
caller's buffer.
To specify this size, the following two definitions are defined by including the <netinet/in.h>
#define INET_ADDRSTRLEN 16 /* for IPv4 dotted-decimal */
#define INET6_ADDRSTRLEN 46 /* for IPv6 hex string */
7. Elementary TCP Sockets
The following fig. shows a timeline of the typical scenario that takes place between a
TCP client and server. First, the server is started, and then sometime later, a client is started that
connects to the server. We assume that the client sends a request to the server, the server
processes the request, and the server sends a reply back to the client. This continues until the
client closes its end of the connection, which sends an end-of-file notification to the server. The
server then closes its end of the connection and either terminates or waits for a new client
connection.
i. socket ( ) Function
To perform network I/O, the first thing a process must do is call the socket( ) function,
specifying the type of communication protocol desired.
#include<sys/socket.h>
int socket(int family, int type, int protocol);
On success the socket ( ) function returns a small non negative integer value, we call this
a socket descriptor or a sockfd.
family: specifies the protocol family {AF_INET for TCP/IP}
type: indicates communications semantics
SOCK_STREAM stream socket TCP
SOCK_DGRAM datagram socket UDP
SOCK_RAW raw socket
protocol: set to 0 except for raw sockets
Example: sd = socket(AF_INET, SOCK_STREAM,0)
Figure. Socket functions for elementary TCP client/server.

ii. connect( ) Function


The connect function is used by a TCP client to establish a connection with a TCP server.
#include<sys/socket.h>
int connect( int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
Return 0 if Ok, -1 on error
sockfd is a socket descriptor that was returned by the socket function.
*servaddr: a pointer to a socket address structure
addrlen: the size of the socket address structure
The socket address structure must contain the IP address and port number of the server.
The connect ( ) function initiates TCP’s three way handshake.
The function returns only when the connection is established or an error occur.
Example: connect (fd, (struct socketaddr*) &servaddr, sizeof(servaddr));
iii. bind( ) Function
The bind( ) function assigns a local protocol address to a socket.
With the Internet Protocols the protocol address is the combination of either a 32-bit IPv4
address, along with 16 bit TCP or UDP port number.
#include<sys/socket.h>
int bind( int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
Return 0 if Ok, -1 on error
sockfd is a socket descriptor that was returned by the socket function.
*myaddr: a pointer to a protocol specific address
addrlen: the size of this address structure
Servers bind their well known port when they start.
If a TCP client or server does not do this, the kernel chooses the temporary port for the
socket when either connect or listen is called.
A process can bind a specific IP address to its socket. The IP address must belong to an
interface on the host.
For a TCP client, this assigns a source IP address and it assigns destination IP address for
TCP server.
iv. listen( ) Function
listen ( ) function is called before the accept function.
It is called only by a TCP server and performs two actions:
1. When a socket is created by the socket function, it is assumed to be an active socket, that
is, a client socket that will issue a connect. The listen function converts an unconnected
socket into a passive socket, indicating that the kernel should accept incoming connection
requests directed to this socket.
2. The second argument (backlog) to this function specifies the maximum number of
connections the kernel should queue for this socket.
#include <sys/socket.h>
int listen (int sockfd, int backlog);
Returns: 0 if OK, -1 on error
This function is normally called after both the socket and bind functions and must be
called before calling the accept function.
To understand the backlog argument, we must realize that for a given listening socket, the kernel
maintains two queues:
1. An incomplete connection queue, which contains an entry for each SYN that has arrived
from a client for which the server is awaiting completion of the TCP three-way
handshake. These sockets are in the SYN_RCVD state.
2. A completed connection queue, which contains an entry for each client with whom the
TCP three-way handshake has completed. These sockets are in the ESTABLISHED state.

The above fig depicts these two queues for a given listening socket.
The above fig. depicts the packet exchanged during the connection establishment with
these two queues.
When a SYN arrives from a client, TCP creates a new entry on the incomplete queue and
then responds with the second segment of the three-way handshake: the server's SYN with
an ACK of the client's SYN.
This entry will remain on the incomplete queue until the third segment of the three-way
handshake arrives.
If the three-way handshake completes normally, the entry moves from the incomplete
queue to the end of the completed queue.
When the process calls accept, first entry on the completed queue is returned to the
process.
v. accept ( ) Function
The accept( ) is called by a TCP server to return the next completed connection from the
front of the completed connection queue.
If the completed connection queue is empty, the process is put to sleep.
#include<sys/socket.h>
int accept( int sockfd, struct sockaddr *cliaddr, socklen_t addrlen);
Return nonnegative descriptor if Ok, -1 on error
sockfd: This is the same descriptor as in listen call.
The cliaddr and addrlen arguments are used to return protocol address of the connected
peer process.
If accept is successful, its return value is a brand-new descriptor automatically created by
the kernel.
This new descriptor refers to the TCP connection with the client.
We call the first argument to accept the listening socket (the descriptor created by socket
and then used as the first argument to both bind and listen), and we call the return value
from accept the connected socket.
It is important to differentiate between these two sockets. A given server normally creates
only one listening socket, which then exists for the lifetime of the server.
The kernel creates one connected socket for each client connection that is accepted.
When the server is finished serving a given client, the connected socket is closed.
The connected socket is closed each time, but the listening socket remains open for the
life of the server.
vi. write ( )Function
#include<unistd.h>
#include<sys/types.h>
int write ( int fd, char *Buff, int NumBytes);
int write ( int file_descriptor, const void *buf, size_t message_length);
Example: int fd; char Buff[ ] = “hello”; write(fd,Buff,strlen(Buff)+1);
The return value is the number of bytes written.
The number of bytes written may be less than the message_length.
This function transfer the data from your application to a buffer in the kernel on your
machine, it does not directly transmit the data over the network.
TCP is in complete control of sending the data and this is implemented inside the kernel.
vii. read ( ) Function
#include<unistd.h>
#include<sys/types.h>
int read ( int fd, char *Buff, int NumBytes);
int read ( int file_descriptor, const void *buf, size_t buffer_length);
Example: int fd; char Buff[50]; read(fd,Buff,sizeof(Buff));
The value returned is the number of bytes read which may not be buffer_length.
This function transfers data from a buffer in the kernel to your application.
viii. close( ) Function
The close ( ) function is used to close a socket and terminate a TCP connection.
#include <unistd.h>
int close (int sockfd);
Returns 0 if Ok, -1 on error.
The default action of close with a TCP socket is to mark the socket as closed and return
to the process immediately.
The socket descriptor is no longer usable by the process:
It cannot be used as an argument to read or write.
But, TCP will try to send any data that is already queued to be sent to the other end, and
after this occurs, the normal TCP connection termination sequence takes place.
A Simple Daytime Client & Server Program
Client
This client establishes a TCP connection with a server and the server simply sends back
the current time and date in a human-readable format.
#include "unp.h"
int main(int argc, char **argv)
{
int sockfd, n;
char recvline[MAXLINE + 1];
struct sockaddr_in servaddr;
if (argc != 2)
err_quit("usage: a.out <IPaddress>");
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
err_sys("socket error");
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(13); /* daytime server */
if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0)
err_quit("inet_pton error for %s", argv[1]);
if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
err_sys("connect error");

while ( (n = read(sockfd, recvline, MAXLINE)) > 0)


{
recvline[n] = 0; /* null terminate */
if (fputs(recvline, stdout) == EOF)
err_sys("fputs error");
}
if (n < 0)
err_sys("read error");
exit(0);
}
Include our own header
We include our own header, unp.h. This header includes many system headers that are
needed by most network programs and defines various constants that we use. (e.g. MAXLINE).
Command line arguments
This is the definition of the main function along with the command-line arguments. We
have written the code in this text.
Create a TCP socket
The socket function creates an Internet (AF_INET) stream (SOCK_STREAM) socket.
The function returns a small integer descriptor that we can use to identify the socket in all future
function calls. The if statement contains a call to the socket function, the return value is assigned
to the variable named sockfd, and then a test of whether this assigned value is less than 0. If the
call to socket fails, we terminate the program by calling our own err_sys function. It prints our
error message along with a description of the system error that and terminates the process.
Specify Server’s IP address and port
We fill in an Internet socket address structure (a sockaddr_in structure named servaddr)
with the server's IP address and port number. We set the complete structure to 0 using bzero, set
the address family to AF_INET, set the port number to 13 (which is the well-known port of the
daytime server on any TCP/IP host that supports this service), and set the IP address to the value
specified as the first command-line argument (argv[1]). The IP address and port number fields in
this structure must be in specific formats: We call the library function htons ("host to network
short") to convert the binary port number, and we call the library function inet_pton
("presentation to numeric") to convert the ASCII command-line argument (such as
206.62.226.35 when we ran this example) into the proper format.
Establish connection with server
The connect function is used to establishes a TCP connection with the server specified
by the socket address structure pointed to by the second argument. We must also specify the
length of the socket address structure as the third argument to connect.In the unp.h header,
we #define SA to be struct sockaddr, that is, a generic socket address structure.
Read and display server’s reply
We read the server's reply and display the result using the standard I/O fputs function.
We must be careful when using TCP because it is a byte-stream protocol with no record
boundaries. The server's reply is normally a 26-byte string of the form. When reading from a
TCP socket, we always need to code the read in a loop and terminate the loop when either read
returns 0 (i.e., the other end closed the connection) or a value less than 0 (an error).
Terminate Program
exit terminates the program. Unix always closes all open descriptors when a process
terminates, so our TCP socket is now closed.
Server
#include "unp.h".
#include <time.h>
int main(int argc, char **argv)
{
int listenfd, connfd;
struct sockaddr_in servaddr;
char buff[MAXLINE];
time_t ticks;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzeros(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13); /* daytime server */
Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; )
{
connfd = Accept(listenfd, (SA *) NULL, NULL);
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
Write(connfd, buff, strlen(buff));
Close(connfd);
}
}
Create a TCP socket
The creation of the TCP socket is the same to the client code.
Bind server's well-known port to socket
The server's well-known port (13 for the daytime service) is bound to the socket by filling
in an Internet socket address structure and calling bind. We specify the IP address as
INADDR_ANY, which allows the server to accept a client connection on any interface, in case
the server host has multiple interfaces.
Convert socket to listening socket
By calling listen, the socket is converted into a listening socket, on which incoming
connections from clients will be accepted by the kernel. These three steps, socket, bind, and
listen, are the normal steps for any TCP server to prepare, we call the listening descriptor as
listenfd. The constant LISTENQ is from our unp.h header. It specifies the maximum number of
client connections that the kernel will queue for this listening descriptor.
Accept client connection, send reply
The server process is put to sleep in the call to accept, waiting for a client connection to
arrive and be accepted. A TCP connection uses a three-way handshake to establish a connection.
When this handshake completes, accept returns, and the return value from the function is a new
descriptor (connfd) that is called the connected descriptor. This new descriptor is used for
communication with the new client. A new descriptor is returned by accept for each client that
connects to our server.
The current time and date are returned by the library function time. The next library function,
ctime, converts this integer value into a human-readable string. A carriage return and linefeed are
appended to the string by snprintf, and the result is written to the client by write.
Terminate connection
The server closes its connection with the client by calling close.
8. Iterative Server
An iterative TCP server processes each client’s request completely before moving on to
the next client.
Example
#include "unp.h"
#include <time.h>
int main(int argc, char **argv)
{
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
char buff[MAXLINE];
time_t ticks;
listenfd = Socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13); /* daytime server */
bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
listen(listenfd, LISTENQ);
for ( ; ; )
{
len = sizeof(cliaddr);
connfd = Accept(listenfd, (SA *) &cliaddr, &len);
printf("connection from %s, port %d\n",Inet_ntop(AF_INET, &cliaddr.sin_addr, buff,
sizeof(buff)), ntohs(cliaddr.sin_port));
ticks = time(NULL);
snprintf(buff, sizeof(buff), "%.24s\r\n", ctime(&ticks));
write(connfd, buff, strlen(buff));
close(connfd);
}
}
Here we declare two new variables that are len and cliaddr. The cliaddr contain the client’s
protocol address.
Create a socket by using socket( ) function. It returns a socket descriptor representing an
endpoint.
After the socket descriptor is created, the bind( )function gets a unique name for the socket.
The listen( ) allows the server to accept incoming client connections.
The server uses accept ( ) function to accept an incoming connection request. The accept( )
call will block indefinitely waiting for the incoming connection to arrive.
The result is written to client by using write ( ) function.
The server closes its connection with client by calling close ( ) function.
9. Concurrent Server
When the client request can take longer to service, we do not want to tie up a single server
with one client, we want to handle multiple clients at the same time.
Concurrent server service many clients simultaneously. It can be implemented in UNIX
by using fork system call.
When a connection is established, accept returns, the server calls fork, and the child process
services the client (on connfd, the connected socket) and the parent process waits for
another connection (on listenfd, the listening socket). The parent closes the connected
socket since the child handles the new client.
#include “unp.h”
int main (int arg, char **argv)
{
pid_t pid;
int listenfd, connfd;
socklen_t len;
struct sockaddr_in servaddr, cliaddr;
listenfd = Socket( AF_INET, SOCK_STREAM,0 );
bzero (&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(13);
Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
for ( ; ; )
{
connfd = Accept (listenfd, (SA*)&cliaddr, &len); /* probably blocks */
if( (pid = Fork()) == 0)
{
Close(listenfd); /* child closes listening socket */
doit(connfd); /* process the request */
Close(connfd); /* done with this client */
exit(0); /* child terminates */
}
Close(connfd); /* parent closes connected socket */
}
}
With the fork ( ) command we create another separate process for each request.
The fork( ) command splits the current process into two processes: a parent and a child.
The fork( ) command returns 0 if you are the child, so all must check the return value from
fork ( ).
From this point, the child to process the clients request and the parent can continue on to
accept other request.
However, when a child finishes and exits it needs to inform the parent that it is completed.
The function doit does whatever is required to service the client.
When this function returns, we explicitly close the connected socket in the child.
This is not required since the next statement calls exit, and part of process termination is to
close all open descriptors by the kernel.
We can also visualize the sockets and connection that occur in the above program as
follows. First, following fig shows the status of the client and server while the server is blocked
in the call to accept and the connection request arrives from the client.
Fig: Status of client/server before call to accept returns
Immediately after accept returns, the connection is accepted by the kernel and a new
socket, connfd, is created. This is a connected socket and data can now be read and written
across the connection.
Fig: Status of client/server after return from accept.

The next step in the concurrent server is to call fork. Fig. shows the status after fork
returns.
Fig: Status of client/server after fork returns.

Both descriptors, listenfd and connfd, are shared (duplicated) between the parent and child.
The next step is for the parent to close the connected socket and the child to close the
listening socket.
Fig: Status of client/server after parent and child close appropriate sockets.

This is the desired final state of the sockets. The child is handling the connection with the
client and the parent can call accept again on the listening socket, to handle the next client
connection.
PART A
1. What is a socket?
A socket is a logical endpoint for communication between two hosts on a TCP/IP
network. A socket type is uniquely determined by a triple <domain, type, protocol>.
2. State the differences between TCP and UDP.
Transmission Control Protocol User Datagram Protocol
Connection Oriented Connection less
Sophisticated Simple
Reliable Unreliable
Byte stream protocol Datagram protocol

3. What are the services provided by TCP?


i. Connections between clients and servers.
ii. Reliability
iii. Sequencing
iv. Flow Control
v. Full duplex communication
4. What is Passive open?
The server prepares to accept an incoming connection by calling socket, bind and listen
functions. This is called passive open.
5. What is Active open?
The client connects to the server by calling the connect function. It causes the client to
send a SYN segment which consists of initial sequence number for the data. This is called
Active open.
6. What are the steps in three way handshake?
7. What are the various TCP options?
i. MSS option
ii. Window scale option
iii. Time stamp option
8. What is active close?
The side (client/ server) which calls the close function first, is performing active close.
9. What is passive close?
The side (client/receiver) that receives the FIN segment from the other end performs the
passive close.
10. What is half-close?
When closing the connection among two parties, A party wishing to close its side of the
FIN. The other party sends an ACK for the FIN, it receives from other end. And after the
other party ACKs, the connection is half-closed. The party which sent the FIN can no longer
send data – but the other party may continue to send data. It is possible for data to flow from
the end doing the passive close to the end doing the active close. This is called a half – close.
11. List out the different types of ports.
i. The well known ports (0 to 1023)
ii. The registered ports (1024 to 49151)
iii. The dynamic or private ports (49152 to 65535)
12. What is TIME_WAIT state?
The side (client / server) which is performing the active close has to wait until it gets the FIN
signal from the other end and after this it closes the connection. This waiting state is called
TIME_WAIT state.
13. What are socketing Address structure?
Socket Address Structure is passed as an argument to the socket function. It is used to set
the properties of socket, such as
i. length
ii. family
iii. port number
iv. IP address
14. What is host byte order?
The byte ordering followed by a given system can be in two ways: little endian byte order
or big endian byte order. This is called host byte order.
15. What is network byte order?
In a network, the sending protocol stack and the receiving protocol stack must agree or the
order in which byte is transmitted. This is called network byte order. It uses big endian byte
order.
16. What is the use of htons, htonl, ntohs, ntohl functions?
htons -> Converts 16 bit value from host byte order to network byte order.
htonl -> Converts 32 bit value from host byte order to network byte order.
ntohs -> Converts 16 bit value from network byte order to host byte order.
ntohl -> Converts 32 bit value from network byte order to host byte order.
17. What are the Elementary TCP client socket functions?
socket
connect
read
write
close
18. What are the Elementary TCP server socket functions?
socket
bind
listen
accept
read
write
close
19. What is the use of socket function?
Socket function is used to create a socket that is bound to a specific transport service
provide. It returns a file descriptor that can be used in later function calls that operate on
sockets.
20. What is an incomplete connection queue?
Contains an entry for each client for which three way handshake is not yet completed.
These are the sockets in the SYN_RCVD state.
21. What is a completed connection queue?
Contains an entry for each client with whom three way handshake has completed. These
are the sockets in the ESTABLISHED state.
22. What is SYN_RCVD state?
The sockets in incomplete connection queue are in SYN_RCVD state. The sockets in this
state cannot send or receive data.
23. What is ESTABLISHED state?
The sockets in completed connected queue are in ESTABLISHED state. Sockets in this
state only \, can send and receive data.
24. What is an iterative server?[Nov 08]
Iterative server will tie up a server with a single client. We would not be able to serve the
multiple numbers of clients simultaneously. It is used for simple, short services.
25. What is a concurrent server?
Concurrent servers service many clients simultaneously using timesharing method or by
having different processors. It can be implemented in UNIX by using fork system call.
26. Explain socket structure in brief. [May 09]
27. Distinguish between iterative and concurrent server. [May 09]
28. How shall local and remote socket addresses obtained? [Nov 07, Apr 10]
Connected sockets have two addresses, local and remote. The getsocketpeeraddress
function returns the remote address.
Connected sockets have two addresses, local and remote. The getsocketaddress function
returns the local address.
29. Define socket. List out its type. [May 07]
30. What is the use of bind ( ) system call ? [May 07]
The bind function shall assign a local socket address address to a socket identified by
descriptor socket that has no local socket address assigned. Sockets created with the socket( )
function are initially unnamed; they are identified only by their address family.
Syntax:
int bind( int socket, const struct sockaddr * address, socklen_t address_len);
31.
PART B
1. Explain in detail about TCI/IP protocols (or) Explain the TCP/IP layering in detail with
neat sketch. [May, Dec 07, Dec 08]
Fig- Overview of TCP/IP protocol
Physical & data link layer– all standard protocols
Network layer – IP(IPV4, IPV6), ARP, RARP, ICMP, IGMP
Transport – TCP, UDP
Application
BPF : BSD Packet Filter:
DLPI: Data Link Provider Interface
2. Compare various socket address structures. [Apr 08]
IPV4:Structure of IPv4 address sockaddr_in
#"$ % % & " address sockaddr_in6
Fig:Comparison of socket address structure
UNIX domain
Data link
3. Explain about the Elementary TCP sockets [Dec 07, Apr 10]
Elementary TCP socket functions required to write a complete TCP client and server.
Fig:socket functions
Syntax and explanation of the system calls.All these functions are defined in the header
file #include<sys/socket.h>
Socket: Creating socket
int socket(int family,int type,int protocol)
Bind: Assigns a local protocol address to a socket
int bind(int sockfd,const struct sockaddr *saddr,socklen_t addrlen)
listen :Converts unconnected(active) socket to connected(passive) socket
int listen(int sockfd,int backlog)
Backlog-No. of connections that the kernel should queue for the socket
Connect:Used to establish a connection
int connect(int sockfd,const struct sockaddr *servaddr,socklen_t addrlen))
Accept:Accept the connection and return the next completed connection from the front of
completed connection queue.
int accept(int sockfd,struct sockaddr *cliaddr,socllen_t *addrlen);
Read:Used to read the incoming data from the socket buffer. It returns the no.of bytes
read.
int read(int fd,char *buff,int numbytes)
int readn(int fd,void *buff,size_t nbytes)
int readline(int fd,void *buff,size_t maxlen)
Write: Used to write the data to the socket buffer.It returns the no.of bytes written.
int writen(int fd,void *buff,size_t nbytes)
int write(int fd,char *buff,int numbytes)
Close: Close the socket and terminate a TCP connection.
int close(int sockfd)
4. Explain various socket system calls.
Refer above question
5. Explain address conversation function. [Dec 07, Apr 08]
inet_aton: Convert 32 bit binary IPV4 addr in to Dotted decimal string
Syntax :int inet_aton(const char *strptr,struct in_addr *addrptr)
inet_ntoa: Convert Dotted decimal string in to 32 bit binary IPV4 addr
Syntax :int inet_ntoa(struct in_addr inaddr)
inet_addr: Convert 32 bit binary IPV4 addr in to Dotted decimal string
Syntax :in_addr_t inet_addr (const char *strptr)
inet_pton Convert Dotted decimal string(presentation format) in to binary IPV4 & IPV6
addr.(numeric format)
Syntax :int inet_pton(int family,const char *strptr, void *addrptr)
inet_ntop Convert 32 bit binary IPV4 & IPV6 addr in to Dotted decimal string
Syntax :int inet_pton(int family, const char *strptr, void *addrptr)
6. Byte ordering functions [Apr 08]
Little-endian byte order big-endian byte order
Fig: Little and big-endian byte order for 16-bit integer
Program to determine host byte order
#include<netinet/in.h>
uint16_t htons(uint16_t host16bitvalue)
uint32_t htonl(uint32_t host32bitvalue)
uint16_t ntohs(uint16_t net16bitvalue)
uint32_t ntohl(uint32_t net32bitvalue)
7. Iterative and Concurrent Server [May, Dec 07, Apr,Dec 08]
Concurrent server:
Used to handle multiple clients by a single server.
Call socket()
bind()
listen()
accept()
fork() system call is used to create a new process
close()
Iterative server:
Processes each clients request completely before moving on to the next client.
Program for Iterative server
o Call socket()
o bind()
o listen()
o accept(),write(),close()
8. Establish connection establishment in TCP. [Dec 09]
9. How is fragmentation done at IP layer? [Dec 09]
10. Explain the operation of iterative servers and concurrent servers from programming
point of view. [Dec 09]
11. Explain the following system calls with examples: connect ( ), listen( ), accept( ), write( ).
12. Write short notes on socket programming. [Apr 10]
13. Discuss the issues of various address conversion functions. [Apr 10]
14. Write short notes on socket creation function, Byte ordering functions, Address
conversion functions. [May 09]

*****************************

You might also like