/* CSC 145/290 Threaded Client/Server Lab */ /* This is an in-lab exercise designed to help you with the exam. You will be in a team with 4 people. Each team will get a number. Each team will be divided into two subgroups: server group (2 persons) and client group (2 persons). For the lab, one group of you must must modify the server below so that the client threads will have access to a shared data structure: char buffer[32][64]; *********** NOTE: instead of the above, allocate memory for stack as follows: int i; char * buffer[32]; for(i=0;i<32;i++) buffer[i] = (char *)malloc(64); This buffer represents a STACK of up to 32 strings, each with up to 64 chars. Each client that connects to the server will send the server a string to push on top of the stack. (you need to maintain a "top of stack" index to indicate the current top of the stack.) The server terminates when the stack is full (print out all the strings in the stack before exiting). This means that you must add synchronization mechanisms to prevent the buffer from being modified simultaneously. Server Group: You are to modify the server side (use attached template) - that is, add the shared integer information, provide critical-section protection, and terminate the for loop when the stack becomes full. Client Group: Write the client from SCRATCH to connect to the server and send it a string. The strings should be unique (string0, string1, etc...). Use some commonly agreed-to port. Run the program without and with critical-section protection. AFTER LAB: the two groups should switch sides and repeat the lab. */ /* simple multi-threaded server template */ #include #include #include #include #include #include #include #include #include #include #include #define PORT 60001 struct clientinfo { int id; // id assigned by client; int cfd; // socket file descriptor; }; void * clientThread (void * cinfo); int main() { pthread_t ctid; // client thread id int ssocket, cfd; int i, result, clen; struct clientinfo * cinfo; struct sockaddr_in saddr; struct sockaddr_in caddr; ssocket = socket(AF_INET,SOCK_STREAM,0); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = htonl(INADDR_ANY); saddr.sin_port = htons(PORT); bind(ssocket,(struct sockaddr *)&saddr,sizeof(saddr)); listen(ssocket,32); clen = sizeof(caddr); for(i=0;i==i;i=(i+1)%32) { cfd = accept(ssocket,(struct sockaddr *)&caddr,&clen); if (cfd != -1) // success { printf("Connection from %s\n",inet_ntoa(caddr.sin_addr)); cinfo = (struct clientinfo *) malloc(sizeof(struct clientinfo)); cinfo->id = i; cinfo->cfd = cfd; pthread_create(&ctid,NULL,clientThread,cinfo); // close(cfd); -- not needed if not using fork } //if } // main loop exit(0); } void * clientThread(void * cinfo) { char buffer[128]; int cid, cfd, result; cid = ((struct clientinfo *)cinfo)->id; cfd = ((struct clientinfo *)cinfo)->cfd; // no need to close server socket here? /* SERVE THIS CLIENT */ /* this part can be replaced with any kind of interaction */ sprintf(buffer,"You are client %d\n",cid); write(cfd,buffer,strlen(buffer)+1); result = 1; while (result > 0) { result = read(cfd,buffer,128); if (result > 0) printf("Got %10s from client\n",buffer); else printf("Client closed connection\n"); } /* Done with this client */ free((struct clientinfo *)cinfo); close(cfd); } //clientThread