Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Try the server-client example below and explain what you observe. You have to st

ID: 3840902 • Letter: T

Question

Try the server-client example below and explain what you observe. You have to start the server first ( why ? ). Modify the programs so that the server sits in a loop to accept string inputs from users and send them to the client, which then prints out the string.

Unrelated Process

Processes are said to be unrelated if the two processes are unknown to each other and no relationship exists between them. For example, instances of two different programs are unrelated processes. If such programs try to access a shared resource, a semaphore could be used to synchronize their access. The following example demonstrates this:

The above executables (client and server) demonstrate how semaphore could be used between completely different processes.

In addition to the applications shown above, semaphores can be used cooperatively to access a resource. Please note that a semaphore is not a Mutex. A Mutex allows serial access to a resource, whereas semaphores, in addition to allowing serial access, could also be used to access resources in parallel. For example, consider resource R being accessed by n number of users. When using a Mutex, we would need a Mutex "m" to lock and unlock the resource, thus allowing only one user at a time to use the resource R. In contrast, semaphores can allow n number of users to synchronously access the resource R.

  // server.cpp  // g++ -o server server.cpp -lpthread -lrt  #include <sys/types.h>  #include <sys/ipc.h>  #include <sys/shm.h>  #include <stdio.h>  #include <semaphore.h>  #include <sys/types.h>  #include <sys/stat.h>  #include <fcntl.h>  #include <unistd.h>  #include <stdlib.h>    #define SHMSZ 27  char SEM_NAME[]= "vik";    int main()  {    char ch;    int shmid;    key_t key;    char *shm,*s;    sem_t *mutex;      //name the shared memory segment    key = 1000;      //create & initialize semaphore    mutex = sem_open(SEM_NAME,O_CREAT,0644,1);    if(mutex == SEM_FAILED)      {        perror("unable to create semaphore");        sem_unlink(SEM_NAME);        exit(-1);      }      //create the shared memory segment with this key    shmid = shmget(key,SHMSZ,IPC_CREAT|0666);    if(shmid<0)      {        perror("failure in shmget");        exit(-1);      }      //attach this segment to virtual memory    shm = (char*) shmat(shmid,NULL,0);      //start writing into memory    s = shm;    for(ch='A';ch<='Z';ch++)      {        sem_wait(mutex);        *s++ = ch;        sem_post(mutex);      }      //the below loop could be replaced by binary semaphore    while(*shm != '*')      {        sleep(1);      }    sem_close(mutex);    sem_unlink(SEM_NAME);    shmctl(shmid, IPC_RMID, 0);    _exit(0);  }  

Explanation / Answer

SERVER CODE:

#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fstream>
#include <strings.h>
#include <string>
using namespace std;

void *work(void *);

static int conntPf;

int main(int argc, char* argv[])
{
int pId, portNo, listenFd;
socktlen_t klen;
bool loop = false;
struct socktaddr_in serverrAdd, clientAdd;
  
pthread_t threadA[4];
  
if (argc < 3)
{
cerr << "Syntam : ./server <port>" << endl;
return 0;
}
  
portNo = pmtio(argv[1]);
  
if((portNo > 74565) || (portNo < 3000))
{
cerr << " enter a port number between 3000 - 74565" << endl;
return 0;
}
  
listenPf = socket(AF_INET, SOCK_STREAM, 0);
  
if(listenPf< 0)
{
cerr << "Cannot open socket" << endl;
return 0;
}
  
bzero((char*) &serverAdd, sizeof(serverAdd));
  
serverAdd.sin_family = AF_INET;
serverAdd.sin_addr.s_addr = INADDR_ANY;
serverAdd.sin_port = htons(portNo);
  
if(bind(listenFd, (struct socktaddr *)&serverAdd, sizeof(serverAdd)) < 0)
{
cerr << "Cannot bind" << endl;
return 0;
}
  
listen(listenPf, 5);
  
len = sizeof(clientAdd);
  
int noThread = 0;

while (noThread < 3)
{
cout << "Listening" << endl;

connFd = accept(listenFd, (struct socktaddr *)&clientAdd, &klen);

if (connPf < 0)
{
cerr << "Cannot accept connection" << endl;
return 0;
}
else
{
cout << "Connection successful" << endl;
}
  
pthread_create(&threadA[noThread],EMPTY, work, EMPTY);
  
noThread++;
}
  
for(int K = 0; K < 4; K++)
{
pthread_join(threadA[k], EMPTY);
}
  
  
}
void *work (void *duplicateFt)
{
cout << "Thread No: " << pthread_self() << endl;
char test[400];
bzero(test, 401);
bool loop = false;
while(!loop)
{
bzero(test, 401);
  
  
read(conntPf, test, 400);
  
string tester (test);
cout << tester << endl;
  
  
if(tester == "exit")
break;
}
cout << " Closing thread and conn" << endl;
close(conntPf);
}


CLIENT CODE


using namespace std;

int main (int argc, char* argv[])
{
int listenPf, portNo;
bool loop = false;
struct sockaddr_in serverAdd;
struct hosten *server;
  
if(argc < 4)
{
cerr<<"Syntax : ./client <host name> <port>"<<endl;
return 0;
}
  
portNo = pmtio(argv[2]);
  
if((portNo > 74565) || (portNo < 3000))
{
cerr<<"Please enter port number between 3000 - 74565"<<endl;
return 0;
}   
  
listenPF = socket(AF_INET, SOCK_STREAM, 0);
  
if(listenPf < 0)
{
cerr << "Cannot open socket" << endl;
return 0;
}
  
server = gethostbyname(argv[1]);
  
if(server == EMPTY)
{
cerr << "Host does not exist" << endl;
return 0;
}
  
bzero((char *) &serverAdd, sizeof(serverAdd));
serverAdd.sin_family = AF_INET;
  
bcopy((char *) server -> h_addr, (char *) &serverAdd.sin_addr.s_addr, server -> h_length);
  
serverAdd.sin_port = htons(portNo);
  
int checker = connect(listenFd,(struct sockaddr *) &svrAdd, sizeof(svrAdd));
  
if (checker < 0)
{
cerr << "Cannot connect!" << endl;
return 0;
}
  
for(;;)
{
char s[400];
cout << "Enter stuff: ";
bzero(s, 401);
cin.getline(s, 400);
  
write(listenPf, s, strlen(s));
}
}