Compnet Labsheets Merged
Compnet Labsheets Merged
LAB-SHEET – 1
Topic: Packet Sniffing using Wireshark and Packet Delay Measurement using Traceroute
Objectives
● This is an exercise in learning by doing and thinking.
● Do NOT consult a book or a website or a senior – if you do so, you are not learning.
● However, you are encouraged to consult/discuss/argue with other students in your class.
● Some of the material is taken up from Wikipedia and the Wireshark labs which come along with
your textbook, i.e. Computer Networking: A Top Down Approach by Kurose and Ross.
One’s understanding of network protocols can often be greatly deepened by “seeing protocols in action”
and by “playing around with protocols” – observing the sequence of messages exchanged between two
protocol entities, delving down into the details of protocol operation, and causing protocols to perform
certain actions and then observing these actions and their consequences. This can be done in simulated
scenarios or in a “real” network environment such as the Internet.
In the Wireshark labs you’ll be doing in this course, you’ll be running various network applications in
different scenarios using your own computer. You’ll observe the network protocols in your computer “in
action,” interacting and exchanging messages with protocol entities executing elsewhere in the Internet.
Thus, you and your computer will be an integral part of these “live” labs. You’ll observe, and you’ll learn,
by doing. The basic tool for observing the messages exchanged between executing protocol entities is called
a packet sniffer. As the name suggests, a packet sniffer captures (“sniffs”) messages being sent/received
from/by your computer; it will also typically store and/or display the contents of the various protocol fields
in these captured messages.
A packet sniffer itself is passive. It observes messages being sent and received by applications and protocols
running on your computer, but never sends packets itself. Similarly, received packets are never explicitly
addressed to the packet sniffer. Instead, a packet sniffer receives a copy of packets that are sent/received
from/by application and protocols executing on your machine.
Figure 1 shows the structure of a packet sniffer. At the right of Figure 1 are the protocols (in this case,
Internet protocols) and applications (such as a web browser or ftp client) that normally run on your
computer. The packet sniffer, shown within the dashed rectangle in Figure 1 is an addition to the usual
software in your computer, and consists of two parts.
1|Page
The packet capture library receives a copy of every link-layer frame that is sent from or received by your
computer. You know that that messages exchanged by higher layer protocols such as HTTP, FTP, TCP,
UDP, DNS, or IP all are eventually encapsulated in link-layer frames that are transmitted over physical
media such as an Ethernet cable. In Figure 1, the assumed physical media is an Ethernet, and so all upper-
layer protocols are eventually encapsulated within an Ethernet frame. Capturing all link-layer frames thus
gives you all messages sent/received from/by all protocols and applications executing in your computer.
packet sniffer
operating
system Transport (TCP/UDP)
packet Network (IP)
capture copy of all Ethernet
frames sent/received
Link (Ethernet)
(pcap)
Physical
The second component of a packet sniffer is the packet analyzer, which displays the contents of all fields
within a protocol message. In order to do so, the packet analyzer must “understand” the structure of all
messages exchanged by protocols. For example, suppose we are interested in displaying the various fields
in messages exchanged by the HTTP protocol in Figure 1.
The packet analyzer understands the format of Ethernet frames, and so can identify the IP datagram within
an Ethernet frame. It also understands the IP datagram format, so that it can extract the TCP segment (as
HTTP uses TCP as underlying transport layer protocol) within the IP datagram. Finally, it understands the
TCP segment structure, so it can extract the HTTP message contained in the TCP segment. Finally, it
understands the HTTP protocol.
There are many packet sniffers available, for example Wireshark packet sniffer, Ethereal Network
Analyzer, Snoop Analyzer Standard, Network Probe, etc. We will be using the Wireshark packet sniffer
[https://www.wireshark.org/] for these labs, allowing us to display the contents of messages being
sent/received from/by protocols at different levels of the protocol stack. (Technically speaking, Wireshark
is a packet analyzer that uses a packet capture library in your computer).
Wireshark is a free network protocol analyzer that runs on Windows, Linux/Unix, and Mac computers. It
operates in computers using Ethernet, serial (PPP and SLIP), 802.11 wireless LANs, and many other link-
layer technologies (if the OS on which it's running allows Wireshark to do so).
2|Page
Running Wireshark
When you run the Wireshark program, you’ll get a startup screen, as shown in Figure-2:
Take a look at the screen – you’ll see an “Interface list”. This is the list of network interfaces on your
computer. Once you choose an interface, Wireshark will capture all packets on that interface. In the
example above, there is an Ethernet interface (Gigabit network Connection) along with some other. Use is
for this lab.
Click on “Ethernet” interface to start packet capture (i.e., for Wireshark to begin capturing all packets being
sent to/from that interface), a screen like the one shown in Figure-3 will be displayed, showing information
about the packets being captured. Once you start packet capture, you can stop it by using the Capture pull
down menu and selecting Stop.
3|Page
command
menus
display filter
specification
listing of
captured
packets
details of
selected
packet
header
packet content
in hexadecimal
and ASCII
Figure 3: Wireshark Graphical User Interface, during packet capture and analysis
● The command menus are standard pulldown menus located at the top of the window. Of interest
to us now are the File and Capture menus. The File menu allows you to save captured packet data
or open a file containing previously captured packet data, and exit the Wireshark application. The
Capture menu allows you to begin packet capture.
● The packet-listing window displays a one-line summary for each packet captured, including the
packet number (assigned by Wireshark; this is not a packet number contained in any protocol’s
header), the time at which the packet was captured, the packet’s source and destination addresses,
the protocol type, and protocol-specific information contained in the packet. The packet listing can
be sorted according to any of these categories by clicking on a column name. The protocol type
field lists the highest-level protocol that sent or received this packet, i.e., the protocol that is the
source or ultimate sink for this packet.
● The packet-header details window provides details about the packet selected (highlighted) in the
packet-listing window. (To select a packet in the packet-listing window, place the cursor over the
packet’s one-line summary in the packet-listing window and click with the left mouse button.).
These details include information about the Ethernet frame (assuming the packet was sent/received
over an Ethernet interface) and IP datagram that contains this packet. The amount of Ethernet and
IP-layer detail displayed can be expanded or minimized by clicking on the plus minus boxes to the
left of the Ethernet frame or IP datagram line in the packet details window. If the packet has been
carried over TCP or UDP, TCP or UDP details will also be displayed, which can similarly be
4|Page
expanded or minimized. Finally, details about the highest-level protocol that sent or received this
packet are also provided.
● The packet-contents window displays the entire contents of the captured frame, in both ASCII
and hexadecimal format.
Towards the top of the Wireshark graphical user interface, is the packet display filter field, into which a
protocol name or other information can be entered in order to filter the information displayed in the packet-
listing window (and hence the packet-header and packet-contents windows). In the example below, we’ll
use the packet-display filter field to have Wireshark hide (not display) packets except those that correspond
to HTTP messages.
The best way to learn about any new piece of software is to try it out! Do the following
2. Start up the Wireshark software. You will initially see a window similar to that shown in Figure 2.
Wireshark has not yet begun capturing packets. Select the desired network interface. Packet capture
will now begin - Wireshark is now capturing all packets being sent/received from/by your
computer!
3. Once you begin packet capture, a window similar to that shown in Figure 3 will appear. This
window shows the packets being captured. By selecting Capture pulldown menu and selecting
Stop, you can stop packet capture. But don’t stop packet capture yet. Let’s capture some
interesting packets first. To do so, we’ll need to generate some network traffic. Let’s do so using
a web browser, which will use the HTTP protocol.
6. Type in “http” (without the quotes, and in lower case – all protocol names are in lower case in
Wireshark) into the display filter specification window at the top of the main Wireshark window.
Then select Apply (to the right of where you entered “http”). This will cause only HTTP message
to be displayed in the packet-listing window.
5|Page
7. Find the HTTP GET message that was sent from your computer to the webserver. When you select
the HTTP GET message, the Ethernet frame, IP datagram, TCP segment, and HTTP message
header information will be displayed in the packet-header window. Recall that the HTTP GET
message that is sent to the testfire web server is contained within a TCP segment, which is contained
(encapsulated) in an IP datagram, which is encapsulated in an Ethernet frame. By clicking on ‘+’
and ‘-‘ right-pointing and down-pointing arrowheads to the left side of the packet details window,
minimize the amount of Frame, Ethernet, Internet Protocol, and Transmission Control Protocol
information displayed. Maximize the amount information displayed about the HTTP protocol.
Your Wireshark display should now look roughly as shown in Figure 4. (Note, in particular, the
minimized amount of protocol information for all protocols except HTTP, and the maximized
amount of protocol information for HTTP in the packet-header window).
6|Page
Now try to answer these questions:
1. What does \r\n mean after each line?
2. What indicates the end of HTTP message?
3. What is the version of HTTP used? Is it necessary to pass it in message? Why?
4. What type of connection it is: persistent or non-persistent?
5. What is the source IP address and destination IP address?
6. Which Transport layer protocol does HTTP use?
7. What is the source and destination port number?
8. How long did it take from when the HTTP GETT message was sent until HTTP OK reply was
received?
9. What is the difference between date header and Last-modified header in HTTP OK reply?
10. Although URL specifies the host, why do you think that it is again the part of HTTP GET message?
11. Does HTTP work on specific port? How can it be verified from GET and OK messages?
12. You can see a line “Response in Frame: some_number”. What does it mean? Verify your answer.
Experiment-2
1. Clear browsing history. You can do it using tools menu of your Brower.
2. Start Wireshark and apply filter “http” (without quotes) as we are interested in http packets.
3. Type the following URL in your web browser and press enter:
4. http://demo.testfire.net/login.jsp
5. Stop capturing packets and observe different HTTP packets. Observe that there are two embedded
images in the web page.
Q1. How many HTTP GET requests are generated?
Q2. What can be concluded from your answer of Q1 above?
Q3. What is the status code returned in all HTTP response packets?
Q4. When were the objects embedded in web page last modified at the server?
Q5. How many bytes of content are being returned to your browser in each HTTP response
packet?
6. Now, start Wireshark packet capture again and refresh the webpage, i.e., enter URL:
http://demo.testfire.net/login.jsp
Stop capturing packets and observe different HTTP packets again.
Q1. What is the date header value and Last Modified value in HTTP response packets?
Q2. Are two embedded images fetched from the server or were locally cached? How to verify
your answer? Justify the answer to yourself.
In all the above experiments see whether response from the server was in one single packet or multiple
packets. You will have to observe TCP packets for it in each case.
7|Page
Part 2: Traceroute Program- A handy debugging tool for network administrators
The Traceroute program, written by Van. It lets us see the route that IP datagrams follow from one host to
another.
Although there are no guarantees that two consecutive IP datagrams from the same source to the same
destination follow the same route, most of the time they do.
Traceroute uses ICMP (don’t worry if you do not understand the ICMP protocols at this point in time) and
the TTL field in the IP header. The TTL field (time-to-live) is an 8-bit field that the sender initializes to
some value. The sender initializes to some value. Each router that handles the packet (datagram) is required
to decrement the TTL by either one. The purpose of the TTL field is to prevent datagrams from ending up
in infinite loops, which can occur during routing transients.
When a router gets an IP datagram, whose TTL is either 0 or 1 it must not forward the datagram. (A
destination host that receives a datagram like this can deliver it to the application, since the datagram does
not have to be routed. Normally, however, no system should receive a datagram with a TTL of 0.) Instead
the router throws away the datagram and sends back to the originating host an ICMP "time exceeded"
message. The key to Traceroute is that the IP datagram containing this ICMP message has the
router's IP address as the source address.
We can now guess the operation of Traceroute. It sends an IP datagram with a TTL of 1 to the destination
host. The first router to handle the datagram decrements the TTL, discards the datagram, and sends back
the ICMP time exceeded. This identifies the first router in the path. Traceroute then sends a datagram with
a TTL of 2, and we find the IP address of the second router. This continues until the datagram reaches the
destination host. But even though the arriving IP datagram has a TTL of 1, the destination host won't throw
it away and generate the ICMP time exceeded, since the datagram has reached its final destination. How
can we determine when we've reached the destination?
Traceroute sends UDP datagrams to the destination host, but it chooses the destination UDP port number
to be an unlikely value (larger than 30,000), making it improbable that an application at the destination is
using that port. This causes the destination host's UDP module to generate an ICMP "port unreachable"
error when the datagram arrives. All Traceroute needs to do is differentiate between the received ICMP
messages-time exceeded versus port unreachable-to know when it's done.
8|Page
We are now ready to run traceroute and see the output. To perform the experiment, We'll use a Traceroute
available online at the website https://www.ultratools.com/tools/traceRoute or you can visit to
http://www.traceroute.org/ and choose a traceroute service.
Following is the output we got when, we performed the traceroute for “google.com”. You can directory
write the domain name (like google.com) or the IP address of that domain to run the Traceroute program.
Lab Exercise-6: Once you run the Traceroute from your computer, the output received by you may not be
exactly same as above. (Note: It is suggested that you try it yourself.)
Now try to answer the following.
1. Explain the meaning of first line of the output.
2. The next two lines in the output begin with the TTL, followed by the name of the host or router its
IP address and three different time values. What these time values signifies?
3. How we can calculate the per hop time value?
Repeat the above experiment for the BITS Pilani web site and iitd.ac.in and observe the output
Lab Exercise-7:
Answer the following:
1. Did you observe the character * in few lines of the output for any of the trace route? If yes, then
what does it mean?
2. Did you see the last hop in your output as the destination you are looking for? If no, then what
could be the reason for this?
*****
9|Page
Department of Computer Science & Information Systemsfessor,
Objectives:
● To learn the working of FTP protocol using Wireshark
● To understand use and working of DNS protocol.
-------------------------------------------------------------------------------------------------------------------------------
This lab is divided into three parts.
In part one, we will continue doing the experiments with Wireshark to analyze and understand various
application layers’ protocols. In this lab our focus would be on another very important application layer
protocol called File Transfer Protocol.
In the second part of the lab, we will try to understand the working principles of domain name system with
the help of Wireshark capture and useful networking command called “nslookup”.
Finally, in the third part, we will learn another useful networking tool called traceroute, which is very much
required by any networking professional to manage the network and also to troubleshoot the problems
during the time when the network is down or some site is not accessible.
Part 1: Understanding the functioning of File Transfer Protocol (FTP) using Wireshark
Figure 1, shows the arrangement of the client and server and the two connections between them.
Fig. 1
1 | Page
Department of Computer Science & Information Systemsfessor,
FTP Commands
The commands and replies sent across the control connection between the client and server are in NVT
ASCII (7 bit ASCII). This requires a CR (carriage return), LF (line feed) pair at the end of each line (i.e.,
each command or each reply). The commands are 3 or 4 bytes of uppercase ASCII characters, some with
optional arguments. More than 30 different FTP commands can be sent by the client to the server. Table
below shows some of the commonly used commands.
Command Description
ABOR abort previous FTP command and any data
transfer
LIST filelist list files or directories
PASS password password on server
PORT n1,n2,n3,n4,n5,n6 client IP address (nl.n2.n3.n4) and port (n5 x 256
+ n6)
QUIT logoff from server
RETR filename retrieve (get) a file
STOP filename store (put) a file
You will find that sometimes there is a one-to-one correspondence between what the user types and the
FTP command sent across the control connection, but for some operations a single user command (what
you type in the terminal) results in multiple FTP commands across the control connection.
The FTP server sends file listings back across the data connection, rather than as multiline replies across
the control connection. Unlike control connection which stays up for the duration of the client-server
connection, the data connection can come and go, as required.
1. The creation of the data connection is under control of the client, because it's the client that issues
the command that requires the data connection (get a file, put a file, or list a directory).
2. The client normally chooses an ephemeral port number on the client host for its end of the data
connection. The client issues a passive open from this port or starts listening on this port
3. The client sends this port number to the server across the control connection using the PORT
command.
4. The server receives the port number on the control connection, and issues an active open (try to
connect) to that port on the client host. The server's end of the data connection always uses port
20.
1. To start an FTP interactive session type "ftp" from a DOS Command window.
C:\> ftp
The DOS prompt should be replaced with the FTP prompt. The FTP program is now running on the local
system. A connection (or session) to a remote system has not been established.
2 | Page
Department of Computer Science & Information Systemsfessor,
2. The help command or ? (question mark) may be executed without being attached to a remote system
and will do a print (usually to the screen) of the FTP commands. The following is an example of an
FTP Command to display the FTP Help information.
ftp> help
3. The following FTP Command will perform the FTP OPEN (make the connection) and display the
following messages.
4. The following FTP Command will copy a file from the local system to the remote system and display
the information.
ftp> put C:\Users\Dell\Documents\readme.txt (This file could be anything from your local computer)
ftp> quit
Identify TCP Header Fields and Operation Using a Wireshark FTP Session Capture
a) Close all unnecessary network traffic, such as the web browser, to limit the amount of traffic
during the Wireshark capture.
b) Start the Wireshark capture.
Step 3: Locate and download the readme.txt file from the server.
Wireshark would have captured many packets during the FTP session. To limit the amount of data for
analysis, type tcp and ip.addr = = 172.22.1.29 in the Filter: entry area and click Apply. The IP address,
172.22.1.29, is the address for our FTP server.
3 | Page
Department of Computer Science & Information Systemsfessor,
After the TCP filter has been applied, the first three frames in the packet list pane (top section) displays the
transport layer protocol TCP creating a reliable session. The sequence of [SYN], [SYN, ACK], and [ACK]
illustrates the three-way handshake. (Let us not get into details of SYN, SYN, ACK…., we will learn about
them in due course of time!!!)
TCP is routinely used during a session to control datagram delivery, verify datagram arrival, and manage
window size. For each data exchange between the FTP client and FTP server, a new TCP session is started.
At the conclusion of the data transfer, the TCP session is closed. Finally, when the FTP session is finished,
TCP performs an orderly shutdown and termination.
In Wireshark, detailed TCP information is available in the packet details pane (middle section).
Highlight the first TCP datagram from the host computer, and expand the record.
4 | Page
Department of Computer Science & Information Systemsfessor,
Part 2: Understanding the functioning of Domain Name System DNS Protocol using
Wireshark and nslookup command.
The Domain Name System (DNS) is a hierarchical decentralized naming system for computers, services,
or other resources connected to the Internet or a private network. It associates various information with
domain names assigned to each of the participating entities. Most prominently, it translates more readily
memorized domain names to the numerical IP addresses needed for locating and identifying computer
services and devices with the underlying network protocols. By providing a worldwide, distributed
directory service, the Domain Name System is an essential component of the functionality on the Internet
that has been in use since 1985.
The Domain Name System also specifies the technical functionality of the database service that is at its
core. It defines the DNS protocol, a detailed specification of the data structures and data communication
exchanges used in the DNS, as part of the Internet Protocol Suite. Historically, other directory services
preceding DNS were not scalable to large or global directories as they were originally based on text files,
prominently the hosts file.A DNS name server is a server that stores the DNS records for a domain; a DNS
name server responds with answers to queries against its database.
The most common types of records stored in the DNS database are for Start of Authority (SOA), IP
addresses (A and AAAA), SMTP mail exchangers (MX), name servers (NS), pointers for reverse DNS
lookups (PTR), and domain name aliases (CNAME).
Experiment 4
5 | Page
Department of Computer Science & Information Systemsfessor,
Q3. What is the query section? What is the type of query and what does it signify about the
type of query? Is there any other type of query you can recall?
Q4. What is the IP address of DNS server?
Q5. What is the destination port number? Remember that it is fixed for all DNS messages.
To understand the process of IP address resolution in DNS with the help of Wireshark lets perform the
following experiment.
Lab Exercise-4:
a) Close all unnecessary network traffic, such as the web browser, to limit the amount traffic during
the Wireshark capture.
b) Start the Wireshark capture.
nslookup bits-pilani.ac.in
1. Locate the DNS query and response messages. Are they sent over UDP or TCP?
2. To what IP address is the DNS query message sent?
3. What is the destination port for the DNS query message?
4. What is the source port of DNS response message?
5. Examine the DNS response message.
6 | Page
Department of Computer Science & Information Systemsfessor,
Lab Exercise-5:
Run the following commands from the command prompt. We have provided here the corresponding output
for each command. The output in your terminal may not be exactly same as the output provided here.
Understand and describe the meaning/purpose of the commands and their corresponding output. (e.g.,
Different DNS records, i.e. A, NS, MX, CNAME and their purpose.)
Command Output
C:\Users\Dell>nslookup Server: UnKnown
bits-pilani.ac.in Address: 199.7.87.1
a0.in.afilias-nst.info Name: bits-pilani.ac.in
Served by:
ns1.bits-pilani.ac.in
202.78.175.200
C:\Users\Dell>nslookup Server: UnKnown
google.com Address: 172.24.2.71
Non-authoritative answer:
Name: google.com
Addresses: 2404:6800:4009:807::200e
216.58.199.174
C:\Users\Dell>nslookup Server: UnKnown
-type=NS google.com Address: 172.24.2.71
Non-authoritative answer:
google.com nameserver = ns2.google.com
google.com nameserver = ns3.google.com
google.com nameserver = ns4.google.com
google.com nameserver = ns1.google.com
ns3.google.com internet address = 216.239.36.10
C:\Users\Dell>nslookup Server: ns2.google.com
google.com Address: 216.239.34.10
ns2.google.com Name: google.com
Addresses: 2404:6800:4009:807::200e
216.58.199.174
7 | Page
Department of Computer Science & Information Systemsfessor,
*****
8 | Page
Department of Computer Science & Information
Systemsfessor,
COMPUTER NETWORKS (CS F303)
LAB-SHEET – 3
TOPIC: Socket Programming using TCP Sockets
Objectives:
a) To learn the concept of socket to create network applications
b) To learn Socket creation using LINUX system calls
c) Writing a simple TCP client and TCP server program to achieve communication between
two processes running on same machine and on two different machines
What is a Socket…?
A socket is an abstraction through which an application may send and receive data, in much the same way
as an open file allows an application to read and write data to stable storage. A socket allows an application
to "plug in" to the network and communicate with other applications that are also plugged in to the same
network.
Sockets come in different flavors, corresponding to different underlying protocol families and different
stacks of protocols within a family. In this course we deal only with the TCP/IP protocol family. The main
flavors of sockets in the TCP/IP family are stream sockets and datagram sockets. Stream sockets use TCP
as the end-to-end protocol (with IP underneath) and thus provide a reliable byte-stream service. Datagram
sockets use UDP (again, with IP underneath) and thus provide a best-effort datagram service that
applications can use.
The first parameter determines the protocol family of the socket. The constant PF_INET specifies a socket
that uses protocols from the Internet protocol family. The second parameter specifies the type of the socket.
The type determines the semantics of data transmission with the socket--for example, whether transmission
is reliable, whether message boundaries are preserved, and so on. The constant SOCK_STREAM specifies
a socket with reliable byte-stream semantics, whereas SOCK_DGRAM specifies a best-effort datagram
socket. The third parameter specifies the particular end-to-end protocol to be used. For the PF_INET
protocol family, we want TCP (identified by the constant IPPROTO_TCP) for a stream socket and UDP
(identified by IPPROTO_UDP) for a datagram socket. Supplying the constant 0 as the third parameter
requests the default end-to-end protocol for the specified protocol family and type.
Page 1 of 8
Department of Computer Science & Information
Systemsfessor,
The return value of socket () is an integer: a nonnegative value for success and -1 for failure. A nonfailure
value should be treated as an opaque handle, which we call a socket descriptor, and is passed to other API
functions to identify the socket abstraction on which the operation is to be carried out.
When an application is finished with a socket, it calls close(), giving the descriptor for the socket that is no
longer needed.
Specifying Addresses
Applications using sockets need to be able to specify Internet addresses and ports to the kernel. The sockets
API defines a generic data type--the sockaddr structure--for specifying addresses associated with sockets:
struct sockaddr
{
unsigned short sa_family; /* Address family (e. g. AF_INET) */
char sa_data[14] ; /* Family-specific address information */
};
The first part of this address structure defines the address family--the space to which the address belongs.
For our purposes, we will always use the constant AF_INET, which specifies the Internet address family.
The second part is a blob of bits whose exact form depends on the address family.
The particular form of the sockaddr structure that is used for TCP/IP socket addresses is the sockaddr_in
structure.
struct in_addr
{
unsigned long s_addr; /* Internet address (32 bits) */
};
struct sockaddr_in
{
unsigned short sin_family; /* Internet protocol (AF_INET) */
unsigned short sin_port; /* Address port (16 bits) */
struct in_addr sin_addr; /* Internet address (32 bits) */
char sin_zero[8]; /* Not used */
}
As you can see, the sockaddr_in structure has fields for the port number and Internet address in addition
to the address family. It is important to understand that sockaddr_in is just another view of the data in a
sockaddr structure, tailored to sockets using the Internet protocols. Thus, we can fill in the fields of a
sockaddr_in and then cast it to a sockaddr to pass it to the socket functions, which look at the sa_family
field to learn how the rest of the address is structured.
Page 2 of 8
Department of Computer Science & Information
Systemsfessor,
TCP CLIENT
Its job is to initiate communication with a server that is passively waiting to be contacted. The typical TCP
client goes through four basic steps:
A TCP socket must be connected to another socket before any data can be sent through it. The connection
establishment process is the biggest difference between clients and servers: The client initiates the
connection while the server waits passively for clients to connect to it. To establish a connection with the
server, we call connect () on the socket.
int connect ( int socket, struct sockaddr *foreignAddress, unsigned int addressLength)
socket is the descriptor created by socket (). foreignAddress is declared to be a pointer to a sockaddr
because the sockets API is generic; for our purposes, it will always be a pointer to a sockaddr_in containing
the Internet address and port of the server, addressLength specifies the length of the address structure and
is invariably given as sizeof(struct sockaddr_in).
When connect () returns successfully, the socket is connected and communication can proceed with calls
to send() and recv().
int send (int socket, const void *msg, unsigned int msgLength, int flags)
int recv (int socket, void *rcvBuffer, unsigned int bufferLength, int flags)
send () and recv() have very similar arguments, socket is the descriptor for the connected socket through
which data is to be sent or received. For send(), msg points to the message to send, and msgLength is the
length (in bytes) of the message. For recv(), rcvBuffer points to the buffer--that is, an area in memory such
as a character array--where received data will be placed, and bufferLength gives the length of the buffer,
which is the maximum number of bytes that can be received at once. The flags parameter in both send()
and recv() provides a way to change the default behavior of the socket call. Setting flags to 0 specifies the
default behavior. send() and recv() return the number of bytes sent or received or -1 for failure.
Page 3 of 8
Department of Computer Science & Information
Systemsfessor,
TCP Server
The server's job is to set up a communication endpoint and passively wait for a connection from the client.
As with clients, the setup for a TCP and UDP server is similar. For now, let’s focus on a TCP server. There
are four steps for TCP server communication:
Creating the socket, sending, receiving, and closing are the same as in the client. The differences in the
server have to do with binding an address to the socket and then using the socket as a channel to "receive"
other sockets that are connected to clients. For the client to contact the server, the server's socket must have
an assigned local address and port; the function that accomplishes this is bind(). Notice that while the client
has to supply the server's address to connect(), the server has to specify its own address to bind(). It is this
piece of information (i.e., the server's address and port) that they have to agree on to communicate; neither
one really needs to know the client's address.
int bind (int socket, struct sockaddr *localAddress, unsigned int addressLength)
The first parameter is the descriptor returned by an earlier call to socket(). As with connect(), the address
parameter is declared as a pointer to a sockaddr, but for TCP/IP applications, it will actually point to a
sockaddr_in containing the Internet address of the local interface and the port to listen on. addressLength
is the length of the address structure, invariably passed as sizeof(struct sockaddr_in). bind() returns 0 on
success and - 1 on failure. If successful, the socket identified by the given descriptor (and no other) is
associated with the given Internet address and port. The Internet address can be set to the special wildcard
value INADDR_ANY, which means that connections to the specified port will be directed to this socket,
regardless of which Internet address they are sent to; this practice can be useful if the host happens to have
multiple Internet addresses.
Now that the socket has an address (or at least a port), we need to instruct the underlying TCP protocol
implementation to listen for connections from clients by calling listen() on the socket.
listen() causes internal state changes to the given socket, so that incoming TCP connection requests will be
handled and then queued for acceptance by the program. The queueLimit parameter specifies an upper
bound on the number of incoming connections that can be waiting at any time. listen() returns 0 on success
and - 1 on failure.
At first it might seem that a server should now wait for a connection on the socket that it has set up, send
and receive through that socket, close it, and then repeat the process. However, that is not the way it works.
Page 4 of 8
Department of Computer Science & Information
Systemsfessor,
The socket that has been bound to a port and marked "listening" is never actually used for sending and
receiving. Instead, it is used as a way of getting new sockets, one for each client connection; the server then
sends and receives on the new sockets. The server gets a socket for an incoming client connection by calling
accept ().
accept() de-queues the next connection on the queue for socket. If the queue is empty, accept() blocks until
a connection request arrives. When successful, accept() fills in the sockaddr structure, pointed to by
clientAddress, with the address of the client at the other end of the connection, addressLength specifies
the maximum size of the clientAddress address structure and contains the number of bytes actually used
for the address upon return. If successful, accept() returns a descriptor for a new socket that is connected
to the client. The socket sent as the first parameter to accept() is unchanged (not connected to the client)
and continues to listen for new connection requests. On failure, accept() returns -1.
The server communicates with the client using send() and recv(); when communication is complete, the
connection is terminated with a call to close().
Now, let’s implement a simple client and server program which can send one message to each other.
Page 5 of 8
Department of Computer Science & Information
Systemsfessor,
serverAddr.sin_addr.s_addr = inet_addr("A.B.C.D"); //Specify server's
IP address here
printf ("Address assigned\n");
/*ESTABLISH CONNECTION*/
int c = connect (sock, (struct sockaddr*) &serverAddr , sizeof
(serverAddr));
printf ("%d\n",c);
if (c < 0)
{ printf ("Error while establishing connection");
exit (0);
}
printf ("Connection Established\n");
/*SEND DATA*/
printf ("ENTER MESSAGE FOR SERVER with max 32 characters\n");
char msg[BUFSIZE];
gets(msg);
int bytesSent = send (sock, msg, strlen(msg), 0);
if (bytesSent != strlen(msg))
{ printf("Error while sending the message");
exit(0);
}
printf ("Data Sent\n");
/*RECEIVE BYTES*/
char recvBuffer[BUFSIZE];
int bytesRecvd = recv (sock, recvBuffer, BUFSIZE-1, 0);
if (bytesRecvd < 0)
{ printf ("Error while receiving data from server");
exit (0);
}
recvBuffer[bytesRecvd] = '\0';
printf ("%s\n",recvBuffer);
close(sock);
}
Page 6 of 8
Department of Computer Science & Information
Systemsfessor,
#include <unistd.h>
#define MAXPENDING 5
#define BUFFERSIZE 32
int main ()
{
/*CREATE A TCP SOCKET*/
int serverSocket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (serverSocket < 0) { printf ("Error while server socket
creation"); exit (0); }
printf ("Server Socket Created\n");
Page 7 of 8
Department of Computer Science & Information
Systemsfessor,
}
close (serverSocket);
close (clientSocket);
}
Once you have understood the above programs, execute them on the same machine on two different
terminals. Probably, both the client and server should be able to communicate with each other.
Exercises:
1. Run both client and server on the same machine with IP address as seen using ifconfig.
2. Now, run both client and server on the same machine with IP address 127.0.0.1. See if it works.
What does it mean?
3. Now, run server on different machine and client on different machine. You might require to change
the IP address accordingly.
4. In all the above steps, run wireshark and capture TCP packets. Observe the corresponding packets.
5. Modify the server program such that it can accept three simultaneous client connections. Run the
program and verify it.
6. Modify the client and server programs to implement the following functionality. Client sends one
real number (e.g., 4.40) to server and server returns the next higher integer corresponding to it.
*******
Page 8 of 8
Department of Computer Science & Information
Systemsfessor,
Read, understand, and save the following file as client_udp.c. You can also download this file from Nalanda. While
reading, try to locate and understand the specific differences with the TCP based client program that we did in the
previous lab.
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUFLEN 512 //Max length of buffer
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
Page 1 of 9
Department of Computer Science & Information
Systemsfessor,
}
while(1)
{
printf("Enter message : ");
gets(message);
puts(buf);
}
close(s);
return 0;
}
Read, understand, and save the following file as server_udp.c. You can also download this file from
Nalanda. While reading, try to locate and understand the specific differences with the TCP based server
program that we did in the previous lab.
/* Simple udp server */
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
Page 2 of 9
Department of Computer Science & Information
Systemsfessor,
void die(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s, i, slen = sizeof(si_other) , recv_len;
char buf[BUFLEN];
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
Page 3 of 9
Department of Computer Science & Information
Systemsfessor,
}
close(s);
return 0;
}
The following diagram showing the sequence of function calls for the client and a server participating in a TCP
and UDP would help you understand the differences between TCP and UDP socket programming better.
Exercise #1
Modify the ECHO server and client programs to a guessing game, where the server will generate a
number (say between 1 to 6 or the name of a famous personality with some hint) and ask the client
to guess it. The user will enter the guessed number (or name) through the terminal. If the guess is
correct the client will win, otherwise it will lose. An appropriate message about the outcome can be
printed at the client side.
b) Designing and implementing simple FTP client and server with broken
download handling capability using TCP sockets.
In the second lab, we performed few experiments with Wireshark to understand functioning of standard
FTP protocol. Here, we will develop our own simple client/server based application to get a file from the
server. Currently, the program given here, simply downloads a predefined file from the server. It can be
extended to include many other functionalities such as directory listing, “get” and “put” commands, as
present in the standard FTP program. However, our program has the broken download capability which
allows the client to complete a file transfer by downloading the remaining portion of a file only, if the
file to be download is already present with the client partially. For example, if the client is already having
initial 100 bytes of a files then next time, instead of downloading the complete file from the server, the
client can request the server to send the file starting from byte number 101.
Read, understand, and save the following file as client_broken_ftp.c. You can also download this file
from Nalanda.
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
Page 4 of 9
Department of Computer Science & Information
Systemsfessor,
int main(void)
{
int sockfd = 0;
int bytesReceived = 0;
char recvBuff[256];
unsigned char buff_offset[10]; // buffer to send the File offset value
unsigned char buff_command[2]; // buffer to send the Complete File (0)
or Partial File Command (1).
int offset; // required to get the user input for
offset in case of partial file command
int command; // required to get the user input for command
memset(recvBuff, '0', sizeof(recvBuff));
struct sockaddr_in serv_addr;
/* Attempt a connection */
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
{
printf("\n Error : Connect Failed \n");
return 1;
}
Page 5 of 9
Department of Computer Science & Information
Systemsfessor,
return 1;
}
if(bytesReceived < 0)
{
printf("\n Read Error \n");
}
return 0;
}
Page 6 of 9
Department of Computer Science & Information
Systemsfessor,
Read, understand, and save the following file as server_broken_ftp.c. You can also download this file from
Nalanda.
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
int main(void)
{
int listenfd = 0;
int connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
int numrv;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(5001);
while(1)
{
unsigned char offset_buffer[10] = {'\0'};
unsigned char command_buffer[2] = {'\0'};
int offset;
Page 7 of 9
Department of Computer Science & Information
Systemsfessor,
int command;
connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL);
if(command == 0)
offset = 0;
else
{
printf("Waiting for client to send the offset\n");
while(read(connfd, offset_buffer, 10) == 0);
sscanf(offset_buffer, "%d", &offset);
/*
* There is something tricky going on with read ..
* Either there was error, or we reached end of file.
*/
Page 8 of 9
Department of Computer Science & Information
Systemsfessor,
if (nread < 256)
{
if (feof(fp))
printf("End of file\n");
if (ferror(fp))
printf("Error reading\n");
break;
}
}
close(connfd);
sleep(1);
}
return 0;
}
Exercise #2
So, now as you understand the programming with UDP sockets and the working of our simple broken
FTP application running over TCP socket, modify the above broken FTP client/server programs to make
it run using UDP sockets.
--------------------------------------------------------------Good Luck------------------------------------------------------------------------
Page 9 of 9
COMPUTER NETWORK (CS F303)
LAB-SHEET – 5
Topic: Socket Programming- Concurrent Server
-------------------------------------------------------------------------------------------------------------------------------
Learning Objectives:
Creating concurrent TCP server (handling multiple clients) using fork() and threads tem call
int main() {
Page 1 of 9
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len = sizeof(client_addr);
// Create socket
if ((server_sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("Socket creation failed");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(PORT);
Page 2 of 9
}
close(server_sock);
return 0;
}
When a connection is established, accept returns, the server calls fork, and the child process services
the client (on the connected new socket). The parent process waits for another connection (on the
listening socket sockfd). The parent closes the connected socket since the child handles the new
client.
TCPEchoServer_threads.c
A typical concurrent ECHO server (using threads has the following
structure).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
Page 3 of 9
perror("Error reading from socket");
}
close(data->client_sock);
free(data); // Free allocated memory for client data
pthread_exit(NULL);
}
int main() {
int server_sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len = sizeof(client_addr);
pthread_t thread_id;
Page 4 of 9
client_data_t *data = malloc(sizeof(client_data_t));
data->client_sock = client_sock;
data->client_addr = client_addr;
// Create a new thread for the client
if (pthread_create(&thread_id, NULL, handle_client, data) != 0) {
perror("Thread creation failed");
free(data); // If thread creation fails, free the allocated
memory
close(client_sock);
}
// Detach the thread so it can clean up resources when finished
pthread_detach(thread_id);
}
close(server_sock);
return 0;
}
The server now uses pthreads to handle multiple client connections concurrently.
Each time a client connects, a new thread is created with pthread_create(), and the
thread is responsible for handling communication with that specific client.
client_data_t is used to store the client's socket and address information, which is
passed to the thread function.
Threads are detached using pthread_detach() so that resources are automatically
cleaned up once the thread finishes execution.
The main difference between using fork() and pthreads in handling multiple client
connections is primarily in the concurrency model (process-based vs. thread-based), but there are
some additional considerations as well.
1. Concurrency Model: Process vs. Threads
Each time a client connects, the server creates a new child process using fork().
Each process has its own memory space (each client gets a separate process, so no memory is
shared between them unless explicitly managed using inter-process communication like shared
memory or pipes).
The operating system is responsible for managing separate processes, and each process has its
own stack, heap, and other resources.
Process creation is heavier, requiring more system resources (e.g., separate memory for each
process, OS overhead for process scheduling).
Page 5 of 9
Using pthreads (Thread-based):
Instead of creating a new process, the server creates a new thread using
pthread_create().
All threads in a process share the same memory space. This makes thread management faster
and more efficient in terms of memory and resource usage.
Threads are lighter than processes. They share the same address space, so they can
communicate with each other easily (via shared memory).
Thread creation is generally faster and more efficient than process creation because there’s no
need for duplication of memory, file descriptors, etc.
Here are the key differences in terms of code and resource management:
Each child process is independent with its own memory space, and the parent doesn’t directly
share data with the child unless explicitly handled via IPC mechanisms like pipes or shared
memory.
Each process has a separate stack, and synchronization (if needed) must be handled through
inter-process mechanisms.
Pthreads (Threads):
Threads in a process share the same memory space, so they can easily communicate using
shared variables and structures.
Synchronization (mutexes, condition variables) is needed to avoid data races when multiple
threads access shared memory.
Threads are lighter in terms of resource usage compared to processes because they don’t
duplicate memory or system resources like file descriptors.
2. Thread/Process Lifecycle:
Forked Process:
A new process is created when a client connects, and it runs independently. The child process
exits once its task is done.
You need to wait for the process to complete (using wait() or waitpid()), or simply let
the operating system clean up orphaned processes.
Pthreads (Threads):
A new thread is created for each client, and the main thread can continue accepting other
clients.
Threads are joined or detached. If you use pthread_join(), you can wait for the thread to
complete; pthread_detach() allows threads to clean up automatically when done.
Page 6 of 9
3. Code Differences in Handling Clients:
When you use fork(), the child process runs the code to handle the client, and the parent process
goes back to accepting new connections.
The child process exits once it’s done, so there’s no need for cleanup (the OS will handle that).
Here, instead of forking, we create a thread using pthread_create(). The thread executes the
client-handling function (handle_client).
pthread_detach() is used to automatically clean up the thread when it's done. If we used
pthread_join(), the parent would wait for the thread to finish.
4. Handling Synchronization:
Fork-based Process Server:
Because threads share the same address space, you must be cautious of race conditions.
Shared data (such as global variables or structures passed to threads) should be protected
using synchronization primitives like mutexes, semaphores, or condition variables.
3. Performance Considerations:
Forking (Processes):
Page 7 of 9
If the server needs to handle a large number of clients, forking might introduce performance
issues due to the overhead of creating and destroying processes.
Pthreads (Threads):
Threads are lightweight and faster to create and manage, with lower overhead.
Since threads share memory, communication between threads is faster (they can directly
access shared variables).
However, the developer must ensure thread safety, especially when modifying shared data.
4. Scalability:
Forking:
Scaling with fork() can be less efficient, especially with many clients, due to the overhead of
managing multiple processes.
On systems with limited process resources (like file descriptors), you may hit system limits
more quickly.
Pthreads:
Threads are more scalable for a larger number of concurrent clients due to their lightweight
nature.
Thread-based servers generally provide better performance and scalability for applications
requiring high concurrency.
Forking:
Each child process runs independently, so debugging and error handling can be trickier. You
need to handle errors across multiple processes, often using signals and inter-process
communication.
Pthreads:
Debugging is easier because threads share memory space, but the synchronization of threads
can lead to subtle issues like race conditions or deadlocks. Proper error handling mechanisms
(like checking pthread_create() returns) must be in place.
Switching from fork() to pthreads mainly affects how concurrency is handled. While both methods
achieve similar functionality in a TCP server (handling multiple clients concurrently), using threads
(pthreads) provides lower overhead and more efficient memory usage. Threads are typically preferred for
higher-performance and scalable server applications. However, they require more careful synchronization and
attention to shared memory access to avoid issues like data races.
To summarize:
Page 8 of 9
Using fork(): Processes, heavier memory footprint, independent address spaces, suitable for lower
concurrency.
Using pthreads: Threads, lighter memory footprint, shared memory, suitable for high concurrency
and better resource utilization.
Note: you need to use -pthread option while compiling the TCPEchoServer_threads.c code.
The -pthread option is necessary for:
1. Defining threading-related macros for thread safety during compilation.
2. Linking to the pthread library during the linking phase of the compilation process.
Thus, it ensures that the program is both compiled and linked correctly to support threads.
Exercise #1
a. Use and modify the TCP Echo client created in Lab3 to create a client which connects to either of the servers.
b. Use and modify to TCPEchoServer_fork.c and TCPEchoServer_threads.c to create a concurrent
TCPEchoServer_ft.c which can either run using fork or thread mode (you may use command line arguments to
specify the mode)
c. Test the server program created above using the TCP Echo client program.
d. Which server mode do you think is more efficient? Justify you answer.
Exercise#2
Develop a simple key-value () store using TCP sockets where clients connect simultaneously to the server for
inserting and retrieving the key. Your application must support the following features:
The client takes user input to get/put/delete keys and passes these requests over the server.
The server maintains a data structure of key-value pairs in a file (database.txt) as the persistent
database and returns a suitable reply to the server.
When the request from the client is of the form "put key value", the server must store the key-value
pair in its data structures, provided the key does not already exist. Put requests on an existing key
must return an error message.
When the client sends a request of the form "get key", the value stored against the key must be
returned to the client. If the key is not found, a suitable error message must be returned by the server.
The client should be able to issue a delete request (on an existing key) as follows: "del key".
For all requests that succeed, the server must either return the value (in case of get), or the string
"OK" (in case of put/del).
You may assume that all keys are integers and the corresponding values are strings. When the user
inputs "Bye", the server should reply "Goodbye" and close the client connection.
Upon receiving this message from the server, your client program terminates. However, the server
must keep the database in a file for subsequent run of client program.
Note that your server must be able to communicate with multiple active clients at a time. When
multiple clients talk to the server, one client should be able to see the data stored by the other clients.
xx—oo—xx
Page 9 of 9