CS 779/879 Design of Network Protocols Spring 2012 Second Exam Time 2 & 1/2 hours Open Book Name: Login: All questions are of equal weights. Question 1: A. Under what condition we can use read/write with a UDP socket. . B. Under what condition we have to use send/recv with a TCP socket. A. If socket is connected. B. To send/recv OOB data. Question 2: A. In assignment 3, the server was implemented using: fork, thread and select. The following is an implementation using Alarm. Modify this code to implement the server using non-blocking IO. Show only necessary changes. int main(int argc, char **argv) { strcpy(GroupIP, argv[1]); strcpy(GroupPort, argv[2]); TCPServer.sin_family = AF_INET; TCPServer.sin_addr.s_addr = htonl(INADDR_ANY); TCPServer.sin_port = htons(atoi(GroupPort)); GroupServer.sin_family = AF_INET; GroupServer.sin_addr.s_addr = htonl(inet_addr(GroupIP)); GroupServer.sin_port = htons(atoi(GroupPort)); UDPSocket = socket(AF_INET, SOCK_DGRAM, 0); bind(UDPSocket, (SA *) & GroupServer, sizeof(GroupServer)); joinGroup(UDPSocket, (char *) GroupIP); setLoopback(UDPSocket, 1); for (i = 0; i <= MAXTCP; i++) connfd[i] = -1; TCPSocket = socket(AF_INET, SOCK_STREAM, 0); bind(TCPSocket, (SA *) & TCPServer, sizeof(TCPServer)); listen(TCPSocket, 4); signal(SIGALRM, handle_ALARM); ualarm(1000); for (;;) { handleUDP(); for (i = 0; i <= MAXTCP; i++) { if (connfd[i] == -1) { connfd[i] = accept(TCPSocket, 0, 0); break; } } for (i = 0; i <= MAXTCP; i++) { if ((connfd[i]) == -1) continue; handleTCP(i); } } } void handleUDP() { recvfrom(UDPSocket, buffer, sizeof(buffer), 0, (SA *)&from, &len)); for (i = 0; i <= MAXTCP; i++) if (connfd[i] != -1) write(connfd[i], buffer, nread); } void handleTCP(int index) { int myIndex = index; nread = read(connfd[myIndex], buffer, sizeof(buffer)); if (nread == 0) { connfd[myIndex] = -1; return; } sendto(UDPSocket,buffer,nread,0,(SA *)&GroupServer,sizeof(GroupServer)); } void handle_ALARM(int signo) { signal(SIGALRM, handle_ALARM); ualarm(1000); } B. Compare the behavior of Chat1 and Chat2 as possible implementations of a chat client. ChatClient.c int sockfd; int main(int argc, char **argv) { int pid; struct sockaddr_in servaddr; struct hostent *hp, *gethostbyname(); sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); hp = gethostbyname(argv[1]); bcopy(hp->h_addr, &(servaddr.sin_addr.s_addr), hp->h_length); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(atoi(argv[2])); if (connect(sockfd,(SA*)&servaddr,sizeof(servaddr))<0) exit(-1); Chat1();// OR Chat2(); } int nread; char buffer[512]; int Chat1() { for (;;) { nread = read(0, buffer, 512); if (nread == 0) return (0); else if (nread > 0) write(sockfd, buffer, nread); nread = read(sockfd, buffer, 512); if (nread == 0) return (0); else if (nread > 0) write(1, buffer, nread); } } int Chat2() { for (;;) { nread = read(sockfd, buffer, 512); if (nread == 0) return (0); else if (nread > 0) write(1, buffer, nread); nread = read(0, buffer, 512); if (nread == 0) return (0); else if (nread > 0) write(sockfd, buffer, nread); } } Chat 2 is deadlocked. Question 3: The following is a pre-threaded echo server that creates on-demand threads if allthe prethreads are busy. Modify the code to use fork instead of threads. Make sure the server cleans up the <defunct> processes. Show only the needed changes. PreOnDemandEchoServerThread.c int len, listenfd, i, NTH, PortNumber; struct sockaddr_in servaddr, cliaddr; pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER; int Available; int main(int argc, char *argv[]) { fd_set rset, allset; int connfd; if (argc != 3) { printf("Usage: %s <Number of Threads> <Port Number>\n", argv[0]); exit(-1); } NTH = atoi(argv[1]); PortNumber = atoi(argv[2]); listenfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PortNumber); bind(listenfd,(SA*)&servaddr,sizeof(servaddr)); listen(listenfd, 0); Available = NTH; for (i = 1; i <= NTH; i++) pthread_create(NULL, NULL, &EchoToClient, NULL); FD_ZERO(&allset); FD_SET(listenfd, &allset); for (;;) { rset = allset; select(4, &rset, NULL, NULL, NULL); pthread_mutex_lock(&mutex1); if (FD_ISSET(listenfd, &rset) && Available == 0) { len = sizeof(cliaddr); connfd = accept(listenfd, (SA *) & cliaddr, &len); pthread_create(NULL,NULL,&TempEchoToClient,(void*)connfd); } pthread_mutex_unlock(&mutex1); } } void *EchoToClient() { int nread; char buffer[512]; int connfd; for (;;) { len = sizeof(cliaddr); pthread_mutex_lock(&mutex1); connfd = accept(listenfd, (SA *) & cliaddr, &len); --Available; pthread_mutex_unlock(&mutex1); doit(connfd); pthread_mutex_lock(&mutex1); ++Available; pthread_mutex_unlock(&mutex1); } } void *TempEchoToClient(void *arg) { int connfd = (int) arg; doit(connfd); pthread_exit(0); } doit(int connfd) { int nread; char buffer[512]; for (;;) { nread = read(connfd, buffer, sizeof(buffer)); if (nread == 0) break; write(connfd, buffer, nread); } } PreOnDemandEchoServerFork.c Question 4: A. In assignment #4, the YouChatC can handle the following set of sockets: {t4, t6, s4, s6, q4, q6, m4, m6, ux} Suppose we like to expand this set to include u4 and u6, where u stands for unicast udp. Briefly explain the necessary modifications to both YouChatC & YouChatS to achieve this goal. YouChatS: need to keep a record of the sender’s addresses to forward the chat messages. B. How did IPv6 manage to quadruple the IP address length while only doubling the overall header length? By eliminating fragmentation and some uncessary fields.