CS 779/879
Design of Network Protocols
Spring 2011
Second Exam
Time 2 & 1/2 hours
Open Book

 

 

                                                                                                      

Name:

 

Login:

 

All questions are of equal weights.


Question 1:

A.     Sometimes we may use read/write with a UDP socket.  Give an example.

 

 

 

 

 

 

 

 

 

 

 

 

B.     Sometimes we have to use send/recv with a TCP socket. Give an example.


Question 2:

Suppose we want to implement a general chat server (GCS) that allows the user to use the following types of chat clients:

TCP, UDP (Unicast or Multicast) and SCTP (Stream or Sequence Packets)  each can use either IPV4 or IPV6.

What is the maximum possible number of different types of chat clients can be used?

What is the minimum possible number of  server sockets  needed  to implement the GCS?

Explain briefly how the server is going to switch the chat messages among all participating clients.

 


Question 3:

The following are several possible implementations of a chat client: f, t, s, n, b1 and b2.

Assuming all chatters will use the same implementation; describe which of these implementations will:

1.      Perfectly perform its function. Do not explain..

2.      Poorly perform its function. Explain why?

3.      Fail  to  perform its function. Explain why?

GeneralChatClient.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);
     if (strcmp(argv[3], "f") == 0) Chat_fork();
     else if (strcmp(argv[3], "t") == 0) Chat_thread();
     else if (strcmp(argv[3], "s") == 0) Chat_select();
     else if (strcmp(argv[3], "n") == 0) Chat_nonblock();
     else if (strcmp(argv[3], "b1") == 0) Chat_block1();
     else if (strcmp(argv[3], "b2") == 0) Chat_block2();
}
int Chat_fork()
{
     int             pid = fork();
     if (pid == 0) {
           HandleSocket();
           kill(getppid(), 9);
     } else {
           HandleStdin();
           kill(pid, 9);
     }
}
int Chat_thread()
{
     pthread_t       tid1;
     pthread_t       tid2;
     pthread_create(&tid1, NULL, &HandleSocket, NULL);
     pthread_create(&tid1, NULL, &HandleStdin, NULL);
     pthread_join(tid1, NULL);
     pthread_join(tid2, NULL);
}

int Chat_select()
{
     fd_set          readset;
     int             nread;
     char            buffer[512];
     for (;;) {
           FD_SET(sockfd, &readset);
           FD_SET(0, &readset);
           select(4, &readset, NULL, NULL, NULL);
           if (FD_ISSET(sockfd, &readset)) {
                nread = read(sockfd, buffer, 512);
                if (nread <= 0) return (0);
                write(1, buffer, nread);
           }
           if (FD_ISSET(0, &readset)) {
                nread = read(0, buffer, 512);
                if (nread <= 0) return (0);
                write(sockfd, buffer, nread);
           }
     }
}
int Chat_nonblock()
{
     int             nread, valu;

     char            buffer[512];
     val = fcntl(sockfd, F_GETFL, 0);
     fcntl(sockfd, F_SETFL, val | O_NONBLOCK);
     val = fcntl(0, F_GETFL, 0);
     fcntl(0, F_SETFL, val | O_NONBLOCK);
     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);
           usleep(100000);
     }
}
int Chat_block1()
{
     int             nread;
     char            buffer[512];
     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 Chat_block2()
{
     int             nread;
     char            buffer[512];
     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);
     }
}
int HandleSocket()
{
     int             nread;
     char            buffer[512];
     for (;;) {
           nread = read(sockfd, buffer, 512);
           if (nread == 0) return (0);
           write(1, buffer, nread);
     }
}
int HandleStdin()
{
     int             nread;
     char            buffer[512];
     for (;;) {
           nread = read(0, buffer, 512);
           if (nread == 0) return (0);
           write(sockfd, buffer, nread);
     }
}


Question 4:

 

The following is a ChatClient code.

Modify this code  to send and receive Out-of-Band data as described below:

§  Any message M typed by the user  that  starts  with the specail character ‘^’  is sent to the server as Out-of-Band data.

§  Any message  M received  from  the server as Out-of-Band data is displayed to the user preceeded with the special character ‘!’

The client may use this mechanism to send and receive non-chat information with the Chat Server.

For example, the client may use it to request  the Server to send back  the list of current chat participants.

 

ChatClient.c

int             sockfd;

int
main(int argc, char **argv)
{

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


        Chat_thread();
}


 

int Chat_thread()
{
        pthread_t       tid1;
        pthread_t       tid2;
        pthread_create(&tid1, NULL, &HandleSocket, NULL);
        pthread_create(&tid1, NULL, &HandleStdin, NULL);
        pthread_join(tid1, NULL);
        pthread_join(tid2, NULL);
}
int HandleStdin()
{

     int             nread;
     char            buffer[512];
     for (;;) {
           nread = read(0, buffer, 512);
           if (nread == 0) return(0);

            write(sockfd, buffer, nread);
               

      }
}
int HandleSocket()
{

     int             nread;
     char            buffer[512];
     for (;;) {
           nread = read(sockfd, buffer, 512);
           if (nread == 0) return(0);
          
           write(1, buffer, nread);
     }
}

 

 

 


 

Question 5:

 

The following is the code for a pre-threaded echo server.

Modify this code so that when  all the pre-threads are busy, the program will  create temporary  on-demand threads.

 

PreEchoServer.c

int             len, listenfd;
struct sockaddr_in servaddr, cliaddr;
int             NThreads;
int             Available;
int             PortNumber;

int
main(int argc, char *argv[])
{

     NThreads = 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);

     if (bind(listenfd,(SA*)&servaddr,sizeof(servaddr))<0)exit(-1);
    
     listen(listenfd, 0);

     Available = NThreads;
     for (i = 1; i <= NThreads; i++) {
           pthread_create(NULL, NULL, &EchoToClient, NULL);
     }

      pause();
}


 

void   *EchoToClient()
{

     int             nread;
     char            buffer[512];
     int             connfd;

     for (;;) {
           len = sizeof(cliaddr);
           connfd = accept(listenfd, (SA *) & cliaddr, &len);
           --Available;
           for (;;) {
                nread = read(connfd, buffer, sizeof(buffer));
                if (nread == 0) {
                     ++Available;
                     break;
                }
                write(connfd, buffer, nread);
           }
     }
}