











Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
This lab report was submitted to Sir Rahul Das at Birla Institute of Technology and Science as lab assignment for Networking course. Its main points are: Inter-Process, Communication, Sockets, Programming, Linux, Environment, Server, Information, Technology
Typology: Exercises
1 / 19
This page cannot be seen from the preview
Don't miss anything!












INTER-PROCESS COMMUNICATION WITH SOCKETS
The objective of this lab is to gain some insight into inter-process communication using sockets. We will learn socket programming in linux environment in C language. Communication will be
carried out between client and server by creating sockets in their routines. Server will listen at its
port number. Client will send its message as a local host to server using its port number. Client
will send a file and server is able to save it in its local directory. Accessing server from a browser
displays a welcome message. Server is able to log its activity in a file in its directory and saves
date and time along with other information.
In computing, Inter-process communication (IPC) is a set of methods for the exchange of data
among multiple threads in one or more processes. Processes may be running on one or more
computers connected by a network. IPC methods are divided into methods for message
passing, synchronization, shared memory, and remote procedure calls (RPC). The method of IPC
used may vary based on the bandwidth and latency of communication between the threads, and the type of data being communicated.
There are several reasons for providing an environment that allows process cooperation:
Information sharing Computational Speedup Modularity Convenience Privilege separation
IPC may also be referred to as inter-thread communication and inter-application communication. The combination of IPC with the address space concept is the foundation for address space independence/isolation. There are two fundamental models of inter-process communication.
Shared memory Message passing
In computing, shared memory is memory that may be simultaneously accessed by multiple programs with intent to provide communication among them or avoid redundant copies. Shared memory is an efficient means of passing data between programs. Depending on context, programs may run on a single processor or on multiple separate processors. Using memory for communication inside a single program, for example among its multiple threads, is generally not referred to as shared memory. In computer hardware, shared memory refers to a (typically) large block of random access memory (RAM) that can be accessed by several different central processing units (CPUs) in a multiple-processor computer system. A shared memory system is relatively easy to program since all processors share a single view of data and the communication between processors can be as fast as memory accesses to a same location.
In computer software, shared memory is either
a method of inter-process communication (IPC), i.e. a way of exchanging data between programs running at the same time. One process will create an area in RAM which other processes can access, or a method of conserving memory space by directing accesses to what would ordinarily be copies of a piece of data to a single instance instead, by using virtual memory mappings or with explicit support of the program in question. This is most often used for shared libraries and for XIP.
Message passing is the paradigm of communication where messages are sent from a sender to one or more recipients. Forms of messages include (remote) method invocation, signals, and data packets. When designing a message passing system several choices are made:
Whether messages are transferred reliably Whether messages are guaranteed to be delivered in order Whether messages are passed one-to-one (unicast), one-to-many (multicast or broadcast), many-to-one (client–server), or many-to-many. Whether communication is synchronous or asynchronous.
Prominent theoretical foundations of concurrent computation, such as the Actor model and the process calculi are based on message passing. Implementations of concurrent systems that use message passing can either have message passing as an integral part of the language, or as a series of library calls from the language. Examples of the former include many distributed object systems. Examples of the latter include Microkernel operating systems that pass messages between one kernel and one or more server blocks, and the Message Passing Interface used in high-performance computing.
Messages are directed and received from mailboxes (also referred to as ports).
Each mailbox has a unique id. Processes can communicate only if they share a mailbox. Link established only if processes share a common mailbox A link may be associated with many processes. Each pair of processes may share several communication links. Link may be unidirectional or bi-directional.
Operations in indirect communication are:
create a new mailbox send and receive messages through mailbox destroy a mailbox Primitives are defined as: Send (A, message) – send a message to mailbox A receive (A, message) – receive a message from mailbox A
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. A socket API is an application programming interface (API), usually provided by the operating system, that allows application programs to control and use network sockets. Internet socket APIs are usually based on the Berkeley sockets standard. A socket address is the combination of an IP address and a port number, much like one end of a telephone connection is the combination of a phone number and a particular extension. Based on this address, internet sockets deliver incoming data packets to the appropriate application process or thread.
An Internet socket is characterized by a unique combination of the following:
Local socket address: Local IP address and port number Remote socket address: Only for established TCP sockets. As discussed in the client-server section below, this is necessary since a TCP server may serve several clients concurrently. The server creates one socket for each client, and these sockets share the same local socket address. Protocol: A transport protocol (e.g., TCP, UDP, raw IP, or others). TCP port 53 and UDP port 53 are consequently different, distinct sockets.
Within the operating system and the application that created a socket, the socket is referred to by a unique integer number called socket identifier or socket number. The operating system forwards the payload of incoming IP packets to the corresponding application by extracting the socket address information from the IP and transport protocol headers and stripping the headers from the application data.
FIGURE 2: SOCKET COMMUNICATION
Create a socket Bind the socket and print out the port number assigned Put the socket into passive mode (listen) while forever do Get next connection Handle the connection end while
Server program should be able to receive and store a text file in its local directory.
Server should be able to receive a file from client and store it in its local directory by the name specified by client.
To implement the given task, following changes were made to the server and client.
Client was able to :
Server was able to :
[se1032@localhost G4]$ ./server The Server passive socket port number is 51864 Ready for a connection... Got a connection - processing... The active server port number is 51864 The active server IP ADDRESS is 127.0.0. The client port number is 54289 The client IP ADDRESS is 127.0.0.
name is : pc.txt command used to save file : cp welc.txt ./servdir/pc.txt the file is saved in the path : /servdir/ Done with connection - closing
[se1032@localhost G4]$ ./client 127.0.0.1 51864
Testing Task 1...
File is created by : zaeem-ul-haq shahzad afzal
syed kumail raza jafri hassan shahid hassan saleem sameer farooq
Following is the code appended in the source files of source and client program.
CLIENT.C
// define a file pointer to open and read the file FILE *pc; int n; // define the name of file char *name="pc.txt"; // create buffer for sending data through socket char buffer[100]; . . . // open the file “pc.txt” pc=fopen("pc.txt","r"); // send file name write(sk,name,strlen(name)); // send the content of file do { n=fread(buffer,1,100,pc); write(sk,buffer,n); }while(n>0); // close the opened file fclose(pc);
SERVER.C // create string to store filename char *name; char buff[100]; // create string to store command char *command; // allocate space for strings to avoid stackoverflow error command = (char *)malloc(100); name = (char *)malloc(7);
int n; // create File pointer to open a file FILE *ptr;
. . . // initialize command and name string as null for(i = 0;i < strlen(command);i=i+1){ command[i] = 0; } for(i=0;i<strlen(name);i=i+1){ name[i] = 0; } // read the name specified by client n=read(sd,name,6); printf("\r\n name is : %s",name); // create a command "cp welc.txt ./servdir/<filename.extension>" command = strncat(command,"cp welc.txt ./servdir/",strlen("cp welc.txt ./servdir/")); // printf("\r\n%s",command); command = strncat(command,name,6); printf("\r\n command used to save file : %s",command); // open a dummy file "welc.txt" ptr=fopen("welc.txt","w"); // write received data in welc.txt do { n=read(sd,buff,100); fwrite(buff,1,n,ptr); }while(n>0); fclose(ptr); // copy the dummy file to the specified local folder with client desired name system(command); // free allocated memory free(command); free(name); // authenticate file saving process printf("\r\nthe file is saved in the path : /servdir/%s",name);
Server program should be able to log its activity.
Server should save any action ,performed by, in a log file.
Server was able to :
Following changes were made in the server source file:
#include <stdio.h> /* standard C i/o facilities / #include <unistd.h> / Unix System Calls / #include <stdlib.h> / standard library / #include <sys/types.h> / system data type definitions / #include <sys/socket.h> / socket specific definitions / #include <netinet/in.h> / INET constants and stuff / #include <arpa/inet.h> / IP address conversion stuff */ #include <string.h> #include <malloc.h>
/* Server main routine - this is an iterative server
int main() { int ld,sd; struct sockaddr_in skaddr; struct sockaddr_in from; int addrlen,length; char buff[1024]; char pdata[1024]; int n,m; FILE *ptr; FILE *dptr; ptr=fopen("./servdir/servdata.log","a");
fprintf(ptr,"\r\nNew Log session\r\n"); /* create a socket IP protocol family (PF_INET) TCP protocol (SOCK_STREAM) */
if ((ld = socket( PF_INET, SOCK_STREAM, 0 )) < 0) { perror("Problem creating socket\n"); exit(1); }
/* establish our address
address family is AF_INET our IP address is INADDR_ANY (any of our IP addresses) the port number is assigned by the kernel */ skaddr.sin_family = AF_INET; skaddr.sin_addr.s_addr = htonl(INADDR_ANY); skaddr.sin_port = htons(0); if (bind(ld, (struct sockaddr ) &skaddr, sizeof(skaddr))<0) { perror("Problem binding\n"); exit(0); } / find out what port we were assigned and print it out */ length = sizeof( skaddr ); if (getsockname(ld, (struct sockaddr ) &skaddr, &length)<0) { perror("Error getsockname\n"); exit(1); } printf("The Server passive socket port number is %d\n",ntohs(skaddr.sin_port)); / put the socket into passive mode (waiting for connections) / if (listen(ld,5) < 0 ) { perror("Error calling listen\n"); fprintf(ptr,"Error calling listen\n"); exit(1); } / now process incoming connections forever ... / fclose(ptr); while (1) { ptr=fopen("./servdir/servdata.log","a"); fprintf(ptr,"Ready for a connection...\n"); addrlen=sizeof(skaddr); if ( (sd = accept( ld, (struct sockaddr) &from, &addrlen)) < 0) { perror("Problem with accept call\n"); fprintf(ptr,"Problem with accept call\n"); exit(1); } fprintf(ptr,"Got a connection - processing...\n");
/* Determine and print out the address of the new server socket */ length = sizeof( skaddr ); if (getsockname(sd, (struct sockaddr ) &skaddr, &length)<0) { perror("Error getsockname\n"); fprintf(ptr,"Error getsockname\n"); exit(1); } fprintf(ptr,"The active server port number is %d\n",ntohs(skaddr.sin_port)); fprintf(ptr,"The active server IP ADDRESS is %s\n",inet_ntoa(skaddr.sin_addr)); / print out the address of the client */ fprintf(ptr,"The client port number is %d\n",ntohs(from.sin_port)); fprintf(ptr,"The client IP ADDRESS is %s\n",inet_ntoa(from.sin_addr));
/* read and send to stdout until the client closes the connection*/ do { m = read(sd,pdata,1024);
if(m >0){ //printf("\r\nSize : Read from socket :%d :%s",m,pdata); system("date > data.log"); dptr = fopen("data.log","r"); n = fread(buff,1,1024,dptr); //printf("Size : Current Date : %d : %s",n,buff); fwrite(buff,1,n,ptr); fclose(dptr); } fwrite(pdata,1,m,ptr); fwrite("\r\n",1,strlen("\r\n"),ptr); }while(m>0); fprintf(ptr,"\r\nDone with connection - closing\n\n\n"); fclose(ptr); close(sd); } }
[se1032@localhost G4]$ ./client 127.0.0.1 34800 hassan [se1032@localhost G4]$ ./client 127.0.0.1 34800 saleem [se1032@localhost G4]$ ./client 127.0.0.1 34800 sammer^H [se1032@localhost G4]$ ./client 127.0.0.1 34800 farooq [se1032@localhost G4]$ ./client 127.0.0.1 34800 shahzad [se1032@localhost G4]$ ./client 127.0.0.1 34800 afzal [se1032@localhost G4]$ ./client 127.0.0.1 34800 zaeem [se1032@localhost G4]$ ./client 127.0.0.1 34800 kumail [se1032@localhost G4]$ ./client 127.0.0.1 34800 hassan_shahifd [se1032@localhost G4]$
Server should display Waiting for a client, current time is hh:mm:ss, dd/mm/yyyy" after every five minutes.
To accomplish this task, following changes were made to the source file:
Source was able to :
Following changes were made to the source file: #include <stdio.h> /* standard C i/o facilities / #include <unistd.h> / Unix System Calls / #include <stdlib.h> / standard library / #include <sys/types.h> / system data type definitions / #include <sys/socket.h> / socket specific definitions / #include <netinet/in.h> / INET constants and stuff / #include <arpa/inet.h> / IP address conversion stuff */ #include <string.h> #include <malloc.h>
/* Server main routine - this is an iterative server
int main() { int ld,sd; struct sockaddr_in skaddr; struct sockaddr_in from; char connection; int addrlen,length; char buff[1024]; char pdata[1024]; int n,m; FILE *ptr; FILE *dptr; FILE conn; connection = '0'; conn = fopen("conenction.txt","w"); fwrite(&connection,1,1,conn); fclose(conn); / create a socket
IP protocol family (PF_INET) TCP protocol (SOCK_STREAM) / if ((ld = socket( PF_INET, SOCK_STREAM, 0 )) < 0) { perror("Problem creating socket\n"); exit(1); } / establish our address address family is AF_INET our IP address is INADDR_ANY (any of our IP addresses) the port number is assigned by the kernel */ skaddr.sin_family = AF_INET; skaddr.sin_addr.s_addr = htonl(INADDR_ANY); skaddr.sin_port = htons(0); if (bind(ld, (struct sockaddr ) &skaddr, sizeof(skaddr))<0) { perror("Problem binding\n"); exit(0); } / find out what port we were assigned and print it out */ length = sizeof( skaddr ); if (getsockname(ld, (struct sockaddr ) &skaddr, &length)<0) { perror("Error getsockname\n"); exit(1); } printf("The Server passive socket port number is %d\n",ntohs(skaddr.sin_port)); / put the socket into passive mode (waiting for connections) */
if (listen(ld,5) < 0 ) { perror("Error calling listen\n"); exit(1); }
/* now process incoming connections forever ... / pid_t PID = fork(); // Child Process if (PID == 0){ / Child/ while(1){ conn = fopen("connection.txt","r"); n = fread(&connection,1,1,conn); fclose(conn); / printf("connection = %c\r\n",connection);/ if(connection == '0'){ system("date +""%r,%e/%m/%Y"" "); printf("Waiting for client...\r\n"); } system("sleep 5s"); }*
} // Parent Process else{ while (1) { printf("Ready for a connection...\n"); addrlen=sizeof(skaddr); if ( (sd = accept( ld, (struct sockaddr) &from, &addrlen)) < 0) { perror("Problem with accept call\n"); exit(1); } connection = '1'; conn = fopen("connection.txt","w"); fwrite(&connection,1,1,conn); fclose(conn); printf("Got a connection - processing...\n"); / Determine and print out the address of the new server socket */ length = sizeof( skaddr ); if (getsockname(sd, (struct sockaddr ) &skaddr, &length)<0) { perror("Error getsockname\n"); exit(1); } printf("The active server port number is %d\n",ntohs(skaddr.sin_port)); printf("The active server IP ADDRESS is %s\n",inet_ntoa(skaddr.sin_addr)); / print out the address of the client */ printf("The client port number is %d\n",ntohs(from.sin_port)); printf("The client IP ADDRESS is %s\n",inet_ntoa(from.sin_addr));
/* read and send to stdout until the client closes the connection*/ ptr=fopen("./servdir/servdata.log","a"); do { m = read(sd,pdata,1024); if(m >0){ printf("\r\nSize : Read from socket :%d :%s",m,pdata); system("date > data.log"); dptr = fopen("data.log","r"); n = fread(buff,1,1024,dptr); printf("Size : Current Date : %d : %s",n,buff); fwrite(buff,1,n,ptr); fclose(dptr); } fwrite(pdata,1,m,ptr); fwrite("\r\n",1,strlen("\r\n"),ptr); }while(m>0); fclose(ptr); printf("\r\nDone with connection - closing\n\n\n"); conn = fopen("connection.txt","w"); connection = '0'; fwrite(&connection,1,1,conn); fclose(conn); close(sd); } } }