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.
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.
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?