CS 779/879 Design of Network Protocols Spring 2012

advertisement
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.
Download