Network Programming
Network Programming
If we compile the program into the default a.out file and execute it, we will have the
followingoutput:
solaris % a.out 206.168.112.96our input
Mon May 26 20:58:40 2003the program's output
3.Protocol Independence
The above program is protocol-dependent on IPv4. We allocate and initialize asockaddr_in structure,
we set the family of this structure to AF_INET, and we specify the firstargument to socket as AF_INET. To
modify the program to work under IPV6, we must change the code. The following figure shows a version
that works under IPV6, with the changes highlighted in bold
1 #include unp.h
2 int
3 main(intargc, char *argv)
4{
5 intsockfd,n;
6 char recvline[MAXLINE+1];
7 structsockaddr_in6servaddr;
8 if(argc!=2)
9 err_quit(usage: a.out<IPaddress>);
10 if((sockfd=socket(AF_INET6,SOCK_STREAM,0))<0)
11 err_sys(socket error);
12 bzero(&servaddr, sizeof(servaddr));
13 servaddr.sin6_family = AF_INET6;
14 servaddr.sin6_port = htons(13); /* daytime server */
15 if (inet_pton(AF_INET6, argv[1], &servaddr.sin6_addr) <= 0)
16 err_quit("inet_pton error for %s", argv[1]);
17 if (connect(sockfd, (SA *) &servaddr, sizeof(servaddr)) < 0)
18 err_sys("connect error");
19 while ( (n = read(sockfd, recvline, MAXLINE)) > 0) {
20 recvline[n]=0;
21 if(fputs(recvline,stdout)==EOF)
22 err_sys(fputs error);
23 }
24 if(n<0)
25 err_sys(read error);
26 exit(0);
27 }
Only five lines are changed, but what we now have is another protocol-dependent program;this time,
it is dependent on IPv6. It is better to make a program protocol-independent.Protocol-independent by using
the getaddrinfofunction (which is called by tcp_connect).
{
int n;
if ( (n = socket(family, type, protocol)) < 0)
err_sys("socket error");
return (n);
}
Whenever you encounter a function name in the text that begins with an uppercaseletter, that is one
of our wrapper functions. It calls a function whose name is the samebut begins with the lowercase letter
While these wrapper functions might not seem like a big savings, we will find that thread functions
do not set the standard Unix errno variable whenan error occurs; instead, the errno value is the return value
of the function. This means thatevery time we call one of the pthread_ functions, we must allocate a
variable, save the returnvalue in that variable, and then set errno to this value before calling err_sys. To
avoidcluttering the code with braces, we can use C's comma operator to combine the assignmentinto errno
and the call of err_sys into a single statement, as in the following:
int n;
if ( (n = pthread_mutex_lock(&ndone_mutex)) != 0)
errno = n, err_sys("pthread_mutex_lock error");
NOTE:
Unixerrno Value: When an error occurs in a Unix function (such as one of the socket functions), the
globalvariable errno is set to a positive value indicating the type of error and the function normallyreturns
1. Our err_sys function looks at the value of errno and prints the correspondingerror message string (e.g.,
"Connection timed out" if errno equals ETIMEDOUT).The value of errno is set by a function only if an
error occurs. Its value is undefined if thefunction does not return an error. All of the positive error values are
constants with alluppercasenames beginning with "E," and are normally defined in the <sys/errno.h>
header.No error has a value of 0.Storing errno in a global variable does not work with multiple threads that
share all global variables.
5. A Simple- Day Time Server
We can write a simple version of a TCP daytime server, which will work with the client from
. We use the wrapper functions.
1 #include "unp.h".
2 #include<time.h>
3 int
4 main(intargc, char **argv)
5{
6 intlistenfd, connfd;
7 structsockaddr_inservaddr;
8 char buff[MAXLINE];
9 time_t ticks;
10 listenfd = Socket(AF_INET, SOCK_STREAM, 0);
11 bzeros(&servaddr, sizeof(servaddr));
12 servaddr.sin_family=AF_INET;
13 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
14 servaddr.sin_port = htons(13); /* daytime server */
15 Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
16 Listen(listenfd, LISTENQ);
17 for ( ; ; ) {
18 connfd = Accept(listenfd, (SA *) NULL, NULL);
19 ticks = time(NULL);
20 snprintf(buff,sizeof(buff),%.24s\r\n, ctime(&ticks));
21 Write(connfd, buff, strlen(buff));
22 Close(connfd);
23 }
24 }
Figure : TCP daytime server.
Create a TCP socket
10 :The creation of the TCP socket is identical to the client code.
Bind server's well-known port to socket
1115 :The server's well-known port (13 for the daytime service) is bound to the socket byfilling 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 server host has multiple interfaces.
Convert socket to listening socket
16 :By calling listen, the socket is converted into a listening socket, on which incomingconnections
from clients will be accepted by the kernel. These three steps, socket, bind, andlisten, are the normal steps
for any TCP server to prepare what we call the listeningdescriptor (listenfd in this example).The constant
LISTENQ is from our unp.h header. It specifies the maximum number of clientconnections that the kernel
will queue for this listening descriptor.
Accept client connection, send reply
1721: Normally, the server process is put to sleep in the call to accept, waiting for a
clientconnection to arrive and be accepted. A TCP connection uses what is called a three-wayhandshake to
establish a connection. When this handshake completes, accept returns, and thereturn value from the
function is a new descriptor (connfd) that is called the connecteddescriptor. This new descriptor is used for
communication with the new client. A new descriptoris returned by accept for each client that connects to
our server.
for(; ; ;)
{
..
} represent the infinite loop.
The current time and date are returned by the library function time, which returns the numberof
seconds since the Unix Epoch: 00:00:00 January 1, 1970, Coordinated Universal Time(UTC). The next
library function, ctime, converts this integer value into a human-readablestring such as
Mon May 26 20:58:40 2003.
A carriage return and linefeed are appended to the string by snprintf, and the result iswritten to the
client by write. Calls to sprintf cannot check for overflow of the destination buffer.snprintf, on the other
hand, requires that the second argument be the size of thedestination buffer, and this buffer will not
overflow.
Terminate connection
22 :The server closes its connection with the client by calling close. This initiates the normal TCP
connection termination sequence: a FIN is sent in each direction and each FIN is acknowledged by the other
end.
TRANSPORT LAYER
Here we focus on the transport layer: TCP, UDP, and Stream Control TransmissionProtocol (SCTP).
Most client/server applications use either TCP or UDP. SCTP is a newerprotocol, originally designed for
transport of telephony signaling across the Internet. Thesetransport protocols use the network-layer protocol
IP, either IPv4 or IPv6.
UDP is a simple, unreliable datagram protocol, while TCP is a sophisticated, reliable bytestream
Protocol. SCTP is similar to TCP as a reliable transport protocol, but it also providesmessage boundaries.
1. Transmission Control Protocol(TCP)
The service provided by TCP to an application is different from the service provided by UDP.TCP is
described in RFC 793 [Postel 1981c], and updated by RFC 1323 [Jacobson, Braden, andBorman 1992],
RFC 2581 [Allman, Paxson, and Stevens 1999], RFC 2988 [Paxson and Allman2000], and RFC 3390
[Allman, Floyd, and Partridge 2002]. First, TCP provides connectionsbetween clients and servers. A TCP
client establishes a connection with a given server,exchanges data with that server across the connection,
and then terminates the connection.
TCP also provides reliability. When TCP sends data to the other end, it requires anacknowledgment
in return. If an acknowledgment is not received, TCP automaticallyretransmits the data and waits a longer
amount of time. After some number ofretransmissions, TCP will give up, with the total amount of time spent
trying to send datatypically between 4 and 10 minutes (depending on the implementation).
TCP contains algorithms to estimate the round-trip time (RTT) between a client and
serverdynamically so that it knows how long to wait for an acknowledgment. For example, the RTTon a
LAN can be milliseconds while across a WAN, it can be seconds. Furthermore, TCPcontinuously estimates
the RTT of a given connection, because the RTT is affected by variations in the network traffic.
TCP also sequences the data by associating a sequence number with every byte that it sends.For
example, assume an application writes 2,048 bytes to a TCP socket, causing TCP to sendtwo segments, the
first containing the data with sequence numbers 11,024 and the secondcontaining the data with sequence
numbers 1,0252,048. (A segment is the unit of data thatTCP passes to IP.) If the segments arrive out of
order, the receiving TCP will reorder the twosegments based on their sequence numbers before passing the
data to the receivingapplication. If TCP receives duplicate data from its peer , it candetect that the data has
been duplicated (from the sequence numbers), and discard theduplicate data.
TCP provides flow control. TCP always tells its peer exactly how many bytes of data it is willingto
accept from the peer at any one time. This is called the advertised window. At any time, thewindow is the
amount of room currently available in the receive buffer, guaranteeing that thesender cannot overflow the
receive buffer. The window changes dynamically over time: As datais received from the sender, the window
size decreases, but as the receiving application readsdata from the buffer, the window size increases. It is
possible for the window to reach 0: whenTCP's receive buffer for a socket is full and it must wait for the
application to read data fromthe buffer before it can take any more data from the peer.
Finally, a TCP connection is full-duplex. This means that an application can send and receivedata in
both directions on a given connection at any time. This means that TCP must keeptrack of state information
such as sequence numbers and window sizes for each direction ofdata flow: sending and receiving.
10
11
12
There are 11 different states defined for a connection and the rules of TCP dictate thetransitions from
one state to another, based on the current state and the segment received inthat state. For example, if an
application performs an active open in the CLOSED state, TCPsends a SYN and the new state is
SYN_SENT. If TCP next receives a SYN with an ACK, it sendsan ACK and the new state is
ESTABLISHED.
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 theFIN_WAIT_1 state.
But if an application receives a FIN while in the ESTABLISHED state (apassive close), the transition is to
the CLOSE_WAIT state.
We denote the normal client transitions with a darker solid line and the normal servertransitions with
a darker dashed line.
Watching the Packets
The following figure shows the actual packet exchange that takes place for a complete TCP
connection:the connection establishment, data transfer, and connection termination.
13
In the above figure we can see that the end that performs theactive close goes through time_wait
state. The duration that this endpoint remains in this state istwice the maximum segment lifetime (MSL),
sometimes called 2MSL.
Every implementation of TCP must choose a value for the MSL. The recommended value in RFC
1122 is 2 minutes. This means the duration of the TIME_WAIT state is 4 minutes.
There are two reasons for the TIME_WAIT state:
1. To implement TCP's full-duplex connection terminationreliably
2. To allow duplicate segments to expire in the network.
The first reason can be explained by looking at the above figure and assuming that the final ACK islost.
The server will resend its final FIN, so the client must maintain state information, allowingit to resend the
final ACK. If it did not maintain this information, it would respond with an RST(a different type of TCP
segment), which would be interpreted by the server as an error. If TCPis performing all the work necessary
to terminate both directions of data flow cleanly for aconnection (its full-duplex close), then it must
correctly handle the loss of any of these foursegments. This example also shows why the end that performs
the active close is the end thatremains in the TIME_WAIT state: because that end is the one that might have
to retransmitthe final ACK.
To understand the second reason for the TIME_WAIT state, assume we have a TCP connectionbetween
12.106.32.254 port 1500 and 206.168.112.219 port 21. This connection is closed andthen sometime later, we
establish another connection between the same IP addresses andports: 12.106.32.254 port 1500 and
206.168.112.219 port 21. This latter connection is calledan incarnationof the previous connection since the
IP addresses and ports are the same. TCPmust prevent old duplicates from a connection from reappearing at
some later time and beingmisinterpreted as belonging to a new incarnation of the same connection. To do
this, TCP willnot initiate a new incarnation of a connection that is currently in the TIME_WAIT state.
Sincethe duration of the TIME_WAIT state is twice the MSL, this allows MSL seconds for a packet inone
direction to be lost, and another MSL seconds for the reply to be lost. By enforcing thisrule, we are
guaranteed that when we successfully establish a TCP connection, all oldduplicates from previous
incarnations of the connection have expired in the network.
2.User Datagram Protocol (UDP)
UDP is a simple transport-layer protocol. It is described in RFC 768. Theapplication writes a
message to a UDP socket, which is then encapsulated in a UDP datagram,which is then further
encapsulated as an IP datagram, which is then sent to its destination.There is no guarantee that a UDP
datagram will ever reach its final destination, that order willbe preserved across the network, or that
datagrams arrive only once.
The problem that we encounter with network programming using UDP is its lack of reliability. Ifa
datagram reaches its final destination but the checksum detects an error, or if the datagramis dropped in the
network, it is not delivered to the UDP socket and is not automaticallyretransmitted. If we want to be certain
that a datagram reaches its destination, we can buildlots of features into our application: acknowledgments
from the other end, timeouts,retransmissions, and the like.
We also say that UDP provides a connectionless service, as there need not be any longtermrelationship between a UDP client and server. For example, a UDP client can create a socketand send a
datagram to a given server and then immediately send another datagram on thesame socket to a different
14
server. Similarly, a UDP server can receive several datagrams on asingle UDP socket, each from a different
client.
15
16
17
18
Port Numbers
At any given time, multiple processes can be using any given transport: UDP, SCTP, or TCP.
Allthree transport layers use 16-bit integer port numbers to differentiate between theseprocesses.
When a client wants to contact a server, the client must identify the server with which it wantsto
communicate. TCP, UDP, and SCTP define a group of well-known ports to identify wellknownservices. For
example, every TCP/IP implementation that supports FTP assigns the well-knownport of 21 (decimal) to the
FTP server. Trivial File Transfer Protocol (TFTP) servers areassigned the UDP port of 69.
Clients, on the other hand, normally use ephemeral ports, that is, short-lived ports. These
portnumbers are normally assigned automatically by the transport protocol to the client. Clientsnormally do
not care about the value of the ephemeral port; the client just needs to be certainthat the ephemeral port is
unique on the client host. The transport protocol code guaranteesthis uniqueness.
The Internet Assigned Numbers Authority (IANA) maintains a list of port number
assignments.Assignments were once published as RFCs; RFC 1700 is the last inthis series. The port
numbers are divided into three ranges:
1. The well-known ports: 0 through 1023. These port numbers are controlled and assignedby the
IANA. When possible, the same port is assigned to a given service for TCP, UDP,and SCTP. For example,
port 80 is assigned for a Web server, for both TCP and UDP, eventhough all implementations currently use
only TCP.
2.The registered ports: 1024 through 49151. These are not controlled by the IANA, but theIANA
registers and lists the uses of these ports as a convenience to the community. Whenpossible, the same port is
assigned to a given service for both TCP and UDP. For example,ports 6000 through 6063 are assigned for an
X Window server for both protocols, eventhough all implementations currently use only TCP.
3. The dynamic or private ports, 49152 through 65535. The IANA says nothing about theseports.
These are what we call ephemeral ports.
19
20
We use the notation {*:21, *: *} to indicate the server's socket pair. The server is waiting for a
connection request on any local interface (the first asterisk) on port 21. The foreign IP address and foreign
port are not specified and we denote them as *:*. We also call this a listening socket.
When we specify the local IP address as an asterisk, it is called the wildcard character. If the host on
which the server is running is multihomed (as in this example), the server can specify that it wants only to
accept incoming connections that arrive destined to one specific local interface. This is a one-or-any choice
for the server. The server cannot specify a list of multiple addresses. The wildcard local address is the "any"
choice.
At some later time, a client starts on the host with IP address 206.168.112.219 and executes an active
open to the server's IP address of 12.106.32.254. We assume the ephemeral port chosen by the client TCP is
1500 for this example.
21
differs from the socket pair for the second connection because the client's TCP chooses an unused port for
the second connection (1501).
22
Since IPv6 routers do not perform fragmentation, there is an implied DF bit with every IPv6
datagram. When an IPv6 router receives a datagram whose size exceeds the outgoing link's MTU, it
generates an ICMPv6 "packet too big" error message.
IPv4 and IPv6 define a minimum reassembly buffer size, the minimum datagram size that we are
guaranteed any implementation must support. For IPv4, this is 576 bytes. IPv6 raises this to 1,500
bytes.
TCP has a maximum segment size (MSS) that announces to the peer TCP the maximum amount of
TCP data that the peer can send per segment.
Standard Internet Services
Following figure lists several standard services that are provided by most implementations of
TCP/IP. Notice that all are provided using both TCP and UDP and the port number is the same for both
protocols.
23