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.


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);
        }
}


Question 3:

 

The following is a pre-threaded echo server that creates on-demand threads if allthe pre-threads 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);

  }

} 


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.


B. How did IPv6 manage to quadruple the IP address length while only doubling the overall header length?