Department of Computing
EE-357: Computer and Communication Networks
Class: BEE-14
Lab 2: Socket Programming for Linux
Time: 14:00 to 17:00
Date: 12-02-2025
Course Instructor: Dr. Hassaan Khalique
Lab Instructor: Rafia Ahmad
Name Reg. no. Lab Performance (10)
Manahil Ahmad 407744
EE347: Computer Networks Page 1
Lab 2: Socket Programming for Linux
Introduction/Objectives:
After this lab, the students should be able to
Explain the concepts of client server communication
Setup client/server communication
Use the sockets interface of C programming language
Implement simple Client / Server applications
Tools/Software Requirements
Ubuntu
Instructions
Read carefully before starting the lab.
These exercises are to be done individually.
To obtain credit for this lab, you are supposed to complete the lab tasks and provide the
source codes and the screen shot of your output in this document (please use red font color)
and upload the completed document to your course’s LMS site.
Avoid plagiarism by copying from the Internet or from your peers.
Background
Application programming interface is a set of rules and protocols that allow one software
application to interact with another. It defines the methods and data formats that applications
can use to communicate with each other.
For example, when you use a weather app, the app might send a request to a weather service's
API to get current weather information. The API defines how the app asks for the data (request)
and how the weather service sends back the information (response).
An API is closely related to a server because it acts as an intermediary that allows clients (such
as applications, websites, or other software) to communicate with a server.
The API defines how the client can request information from the server and how the server
responds with the data. It is the "bridge" between the two.
EE347: Computer Networks Page 2
An API may include specifications for routines, data structures, object classes, and variables.
Here's what an API specifically does:
Facilitates communication between systems
Provides a set of rules or protocols
· How a request is sent
· How the server responds (e.g., the format of the returned data)
· What actions or methods are allowed (e.g., GET for retrieving data, POST for
sending data)
Abstraction of complex functionality: APIs abstract away complex operations, allowing
developers to interact with underlying systems without needing to understand their
inner workings.
Examples of non-network APIs include:
File System APIs: These APIs allow applications to interact with the file system, such
as reading, writing, or modifying files.
Operating System APIs: These APIs let software interact with the underlying operating
system.
Network Application Programming Interface is a type of Application Programming
Interface that allows different devices and systems to communicate over a network, such as the
internet or a local network. It provides a way for applications to interact with network services
and resources, such as servers, databases, or other applications, by sending and receiving data
over the network.
EE347: Computer Networks Page 3
Network Sockets
A network socket is an endpoint of an inter-process communication flow across a computer
network. Today, most communication between computers is based on the Internet Protocol;
therefore most network sockets are Internet sockets.
Socket is an end point of communication between two systems on a network. To be a bit
precise, a socket is a combination of IP address and port on one system. So on each system
a socket exists for a process interacting with the socket on other system over the network. A
combination of local socket and the socket at the remote system is also known a ‘Four tuple’
or ‘4-tuple’. Each connection between two processes running at different systems can be
uniquely identified through their 4-tuple.
TCP/IP networking model is the most popular and widely used. The communication over the
network in TCP/IP model takes place in form of a client server architecture. i.e., the client
begins the communication and server follows up and a connection is established.
Socket API:
A socket API is an interface, usually provided by the operating system, that allows application
programs to control and use network sockets.
How a Socket API Works:
1. The API allows you to create a socket, specifying whether you want to use TCP
(connection-oriented) or UDP (connectionless).
2. Bind to a Port: The socket is assigned a specific network port on your machine.
3. Send and receive raw data over the network.
4. Manage Connections: With TCP, sockets can manage persistent connections for
reliable data transfer.
Internet socket APIs are usually based on the Berkeley sockets standard.
Developed in the early 1980s at the University of California at Berkeley. Other
major alternative was TLI (Transport Layer Interface).
EE347: Computer Networks Page 4
Can use the UNIX read, write, close, select, etc. system calls. Supports
broadcast. This is where the same message may be delivered to multiple systems
on a network without additional overhead.
Client/Server Communication
At a basic level, network-based systems consist of a server, client, and a media for
communication as shown in Figure. A computer running a program that makes a request for
services is called client machine. A computer running a program that offers requested services
from one or more clients is called server machine. The media for communication can be wired
or wireless network.
Figure 1. Client server communication
Generally, programs running on client machines make requests to a program (often called as
server program) running on a server machine. They involve networking services provided by
the transport layer, which is part of the Internet software stack, often called TCP/IP (Transport
Control Protocol/Internet Protocol) stack, the transport layer comprises two types of protocols,
TCP (Transport Control Protocol) and UDP (User Datagram Protocol)
Port Numbers
At any given time, multiple processes can be using any given transport layer protocol: UDP or
TCP. The transport layer uses 16-bit integer port numbers to differentiate between these
processes. When a client wants to contact a server, the client must identify the server with
which it wants to communicate. The TCP and UDP protocols use ports to map incoming data
to a particular process running on a computer. Some ports have been reserved to support
common/well known services:
ftp 21/tcp
smtp 25/tcp
http 80/tcp,udp
User-level process/services generally use port number value >= 1024.
EE347: Computer Networks Page 5
Socket Server Example
This server continuously runs and sends the date and time to client as soon as a client connects
to it.
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include<time.h>
int main(int argc, char *argv[]) {
// port to start the server on
int SERVER_PORT = 8877;
socklen_t client_address_len;
// socket address used for the server
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
// htons: host to network short: transforms a value in host byte
// ordering format to a short value in network byte ordering format
server_address.sin_port = htons(SERVER_PORT);
// htons: host to network long: same as htons but to long
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
// create a UDP socket, creation returns -1 on failure
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("could not create socket\n");
return 1;
}
// bind it to listen to the incoming connections on the created server
// address, will return -1 on error
if ((bind(sock, (struct sockaddr *)&server_address,
sizeof(server_address))) < 0) {
printf("could not bind socket\n");
return 1;
}
// socket address used to store client address
struct sockaddr_in client_address;
// run indefinitely
EE347: Computer Networks Page 6
while (true) {
char buffer[500];
// read content into buffer from an incoming client
int len = recvfrom(sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_address,
&client_address_len);
// inet_ntoa prints user friendly representation of the
// ip address
buffer[len] = '\0';
printf("received: '%s' from client %s\n", buffer,
inet_ntoa(client_address.sin_addr));
// send same content back to the client ("echo")
sendto(sock, buffer, len, 0, (struct sockaddr *)&client_address,
sizeof(client_address));
}
return 0;
}
The call to the function ‘socket()’ creates an socket inside the kernel (kernel is the core
part of an operating system that directly manages a computer's hardware and resources).
For Internet family of IPv4 addresses we use AF_INET.
The second argument ‘SOCK_STREAM’ specifies that the transport layer protocol that
we want should be reliable ie it should have acknowledgement techniques.
The third argument is generally left zero to let the kernel decide the default protocol to
use for this connection. For connection oriented reliable connections, the default
protocol used is TCP.
The call to the function ‘bind()’ assigns the details specified in the structure ‘serv_addr’
to the socket created in the step above.
The call to the function ‘listen()’ with second argument as ’10’ specifies maximum
number of client connections that server will queue for this listening socket.
After the call to listen(), this socket becomes a fully functional listening socket.
In the call to accept(), the server is put to sleep and when for an incoming client request,
the three way TCP handshake* is complete, the function accept () wakes up and returns
the socket descriptor representing the client socket.
The call to accept() is run in an infinite loop so that the server is always running and
the delay or sleep of 1 sec ensures that this server does not eat up all of your CPU
processing.
As soon as server gets a request from client, it prepares the date and time and writes on
the client socket through the descriptor returned by accept().
Three way hand shake is the procedure that is followed to establish a TCP connection between
two remote hosts.
EE347: Computer Networks Page 7
Socket Client Example
In the above program, we create a client which will connect to the server and receive date and
time from it. In the above piece of code:
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <time.h>
int main() {
const char* server_name = "localhost";
const int server_port = 8877;
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
// creates binary representation of server name
// and stores it as sin_addr
inet_pton(AF_INET, server_name, &server_address.sin_addr);
// htons: port in network order format
server_address.sin_port = htons(server_port);
// open socket
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("could not create socket\n");
return 1;
}
// data that will be sent to the server
const char* data_to_send = " You did it!";
// start of clock
clock_t start, end;
double RTT;
start = clock();
// send data
int len =
sendto(sock, data_to_send, strlen(data_to_send), 0,
(struct sockaddr*)&server_address, sizeof(server_address));
// received echoed data back
char buffer[100];
EE347: Computer Networks Page 8
recvfrom(sock, buffer, len, 0, NULL, NULL);
buffer[len] = '\0';
printf("recieved: '%s'\n", buffer);
// end of clock
end = clock();
RTT = ((double) (end - start)) / CLOCKS_PER_SEC;
printf("CPU TIME USED: %f",RTT);
printf("Done");
// close the socket
close(sock);
return 0;
}
We see that here also, a socket is created through call to socket() function.
Information like IP address of the remote host and its port is bundled up in a structure and
a call to function connect() is made which tries to connect this socket with the socket (IP
address and port) of the remote host.
Note that here we have not bind our client socket on a particular port as client generally
use port assigned by kernel as client can have its socket associated with any port but In
case of server it has to be a well-known socket, so known servers bind to a specific port
like HTTP server runs on port 80 etc. while there is no such restrictions on clients.
Once the sockets are connected, the server sends the data (date+time) on clients socket
through clients socket descriptor and client can read it through normal read call on the its
socket descriptor.
Using Virtualbox to run Ubuntu on Windows:
First copy Cnbuntu VDI file from Computer networks folder presses in Downloads of
SSC.
To open SSC downloads folder type \\10.3.20.65 in Run ,User name and password is
“ssc”.
To create new virtual machine using Virtualbox click new in toolbox .
This opens New Virtual Machine Wizard. Click Next:
.
EE347: Computer Networks Page 9
Enter the Ubuntu in name field. Select linux in type field, Ubuntu 64 bit in version field
and click next
Assign 4Gb ram to your virtual machine using the slider and click next
Select the Use an existing virtual hard disk file option, then click on the folder icon to
the right and choose Ubuntu vdi file you copied from SSC. Click Create
Click Start to run your virtual machine
Compiling and running C files on ububtu
Open text editor in Ubuntu and paste server code and save with c extension
EE347: Computer Networks Page 10
Create another c file name Client .c and paste client code in it.
Now open two terminals run server.c code on first terminal and client.c on the other.
Following are the terminal commands to compile and Run server side C code
g++ server.c -o serv.out
for executing
./serv.out
Now one second terminal comple and execute the client as shown below.
g++ client.c -o cli.out
for executing
./cli.out 127.0.0.1
EE347: Computer Networks Page 11
Lab Task 1: (5)
Perform all the steps about and run both servers and client code on same computer. Paste
detailed screenshots and explain what is happening.
Execution Output:
Explanation of Codes:
Server Code Explanation:
The server program is a simple UDP (User Datagram Protocol) echo server that listens for
messages from clients and sends them back. It first sets up a socket using socket(PF_INET,
SOCK_DGRAM, 0), which creates a UDP socket. Then, it binds this socket to a specified port
(8877) and listens for incoming messages. When a client sends a message, the server receives
it using recvfrom(), prints the message along with the client’s IP address, and then sends the
same message back using sendto(). Since UDP is connectionless, there is no need for an explicit
"accept" step like in TCP. The server runs indefinitely in a loop, always ready to receive and
echo messages from clients.
Client Code Explanation:
The client program initiates a UDP connection to the server running on localhost at port 8877.
It first creates a socket using socket(PF_INET, SOCK_DGRAM, 0), then sets up the server’s
address information. It sends a message ("You did it!") using sendto(), and immediately waits
for the echoed response using recvfrom(). Additionally, it measures the round-trip time (RTT)
using clock() before and after sending the message, calculating how long it takes for the
message to travel to the server and back. Finally, it prints the received message and the
computed RTT before closing the socket. This setup demonstrates how UDP communication
works in a simple and efficient way, albeit without guaranteed delivery.
Lab Task 2: (1)
Identify the part in the server code where it returns the time to the client. Amend the code
to display a string: “This lab must be submitted by Monday 11:59 PM.” Explain the
changes you made.
EE347: Computer Networks Page 12
Server Code (Modified):
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
int main(int argc, char *argv[]) {
// Port to start the server on
int SERVER_PORT = 8877;
socklen_t client_address_len = sizeof(struct sockaddr_in);
// Socket address used for the server
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
server_address.sin_port = htons(SERVER_PORT);
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
// Create a UDP socket
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("could not create socket\n");
return 1;
}
// Bind the socket to the server address
if ((bind(sock, (struct sockaddr *)&server_address, sizeof(server_ad-
dress))) < 0) {
printf("could not bind socket\n");
return 1;
}
// Socket address used to store client address
struct sockaddr_in client_address;
// Run indefinitely
EE347: Computer Networks Page 13
while (true) {
char buffer[500];
// Wait for a request from the client
int len = recvfrom(sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_address, &client_ad-
dress_len);
buffer[len] = '\0';
printf("Received request from client %s\n", inet_ntoa(client_ad-
dress.sin_addr));
// Ask the client what to print
const char *prompt_message = "What do you want to print?";
sendto(sock, prompt_message, strlen(prompt_message), 0,
(struct sockaddr *)&client_address, client_address_len);
// Receive the client's message
len = recvfrom(sock, buffer, sizeof(buffer), 0,
(struct sockaddr *)&client_address, &client_ad-
dress_len);
buffer[len] = '\0';
printf("Client wants to print: '%s'\n", buffer);
}
return 0;
}
Client Code (Modified):
#include <arpa/inet.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
int main() {
const char *server_name = "localhost";
const int server_port = 8877;
struct sockaddr_in server_address;
memset(&server_address, 0, sizeof(server_address));
server_address.sin_family = AF_INET;
inet_pton(AF_INET, server_name, &server_address.sin_addr);
server_address.sin_port = htons(server_port);
// Create a UDP socket
EE347: Computer Networks Page 14
int sock;
if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
printf("could not create socket\n");
return 1;
}
// Send a request to the server
const char *request_message = "Request to print";
sendto(sock, request_message, strlen(request_message), 0,
(struct sockaddr *)&server_address, sizeof(server_address));
// Receive the server's prompt
char buffer[500];
int len = recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL);
buffer[len] = '\0';
printf("Server says: %s\n", buffer);
// Get user input for the message to print
printf("Enter your message: ");
fgets(buffer, sizeof(buffer), stdin);
buffer[strcspn(buffer, "\n")] = '\0'; // Remove newline character
// Send the user's message to the server
sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)&server_address, sizeof(server_address));
printf("Message sent to server.\n");
// Close the socket
close(sock);
return 0;
}
Execution Output:
EE347: Computer Networks Page 15
Explanation of the Modifications:
Server Code Changes Explanation:
The server has been modified to enhance its interaction with the client. Initially, it waits for a
request from the client, and once received, it prints the client’s IP address. Instead of echoing
the message immediately, the server now sends a predefined prompt: "What do you want to
print?" to the client, asking for user input. Then, it waits for the client to respond with a
message, which it receives and prints to the console. These changes improve the functionality
by making the server more interactive rather than just echoing messages, making it behave
more like a command-response system.
Client Code Changes Explanation:
The client now follows a more structured exchange with the server. Instead of sending a static
message and waiting for an echo, it first sends a "Request to print" message to initiate
communication. The client then waits for a prompt from the server asking what to print, which
it receives and displays. It then asks the user to input a message, which is read using fgets(),
ensuring that multi-word inputs are handled properly. After processing the input (removing the
newline character), it sends this message back to the server. This change transforms the client
into a more dynamic entity that actively responds to the server’s requests, making the
interaction feel more like a conversation.
Lab Task 3: (4)
1. What does the function socket(AF_INET, SOCK_STREAM, 0) do in the context
of the server? What is the purpose of the bind function in this code, and what
parameters does it take?
socket (AF_INET, SOCK_STREAM, 0) creates a TCP socket that allows the server
to communicate over IPv4. The bind function is used to associate this socket with a
specific IP address and port. It takes three parameters: the socket descriptor, a pointer
to a sockaddr structure (which contains the server’s address and port), and the size of
that structure. Without bind, the server wouldn’t know which address and port to listen
on.
2. Explain what listen does. What does the number 10 represent? How does the
accept function work, and what does it return?
The listen function allows the server to wait for incoming connections. The number 10
represents the maximum number of pending connections that can be queued before the
server starts rejecting new ones. The accept function blocks execution until a client
connects, then returns a new socket descriptor for communication with that specific
client. It also fills a sockaddr structure with the client’s details
3. Why are we using 127.0.0.1 as server’s IP address? Explain.
EE347: Computer Networks Page 16
127.0.0.1 is the loopback IP address, meaning the server is running on the same
machine as the client. This is useful for testing because it avoids network-related issues
like firewalls or router configurations. In real-world scenarios, a public or private IP
would be used instead.
4. How and where did the three-way handshake occur? Explain what it is.
The three-way handshake occurs when a client tries to establish a TCP connection with
the server. It consists of three steps:
(1) The client sends a SYN packet to the server,
(2) The server responds with a SYN-ACK packet, and
(3) The client sends an ACK packet, completing the connection setup.
However, since the provided code is using UDP (not TCP), there is no three-way
handshake in this implementation—UDP is connectionless, meaning data is sent
without a formal handshake
Conclusion:
This lab demonstrated a structured client-server communication using UDP sockets, where the
server interacts dynamically with the client by prompting for user input. Unlike a simple echo
system, the modified approach allows for a more interactive exchange, enabling the client to
send custom messages based on user input. This exercise reinforced key concepts such as
socket creation, message transmission, and user-driven communication, making it a practical
example of real-world network interactions.
EE347: Computer Networks Page 17