15213 Recitation Section CImportant DatesExtending Echo ServerAn Echo Client-Server TransactionReview of the Sockets InterfaceEcho Client Main RoutineEcho Client: open_clientfdEcho Server: Main RoutineEcho Server: open_listenfdEcho Server: open_listenfd (cont)Echo Server: echoProxyChanging ”echo” procedureChanging mainL7 ProxyHTTP Request and ResponseSlide 17HTTP RequestHTTP ResponseBroken Pipe ErrorDetailsHow to deal with broken pipe?Feedback and Evaluation15213 Recitation Section C• Extending echo server• HTTP• Broken pipe error• Feedback and evaluation Shimin ChenNov. 25, 2002Outline215213 Recitation C Shimin ChenImportant Dates•Lab 7 Proxy: due on Thursday, Dec 5•Final Exam: Tuesday, Dec 17315213 Recitation C Shimin ChenExtending Echo Server•We will recap the echo client and server taught in the last lecture•Then we will extend the echo server to build an echo proxy415213 Recitation C Shimin ChenAn Echo Client-Server TransactionEchoClientprocessEchoServerprocess1. Client sends an input line2. Server sends the same text as it receives3. Client displays the text it receives515213 Recitation C Shimin Chenrio_readlinebclosecloseEOFrio_readlinebrio_writenrio_readlinebrio_writenlistenbindReview of the Sockets InterfaceClientServersocket socketacceptconnectConnectionrequestAwait connectionrequest fromnext clientopen_listenfdopen_clientfd615213 Recitation C Shimin ChenEcho Client Main Routine#include "csapp.h" /* usage: ./echoclient host port */int main(int argc, char **argv){ int clientfd, port; char *host, buf[MAXLINE]; rio_t rio; host = argv[1]; port = atoi(argv[2]); clientfd = Open_clientfd(host, port); Rio_readinitb(&rio, clientfd); while (Fgets(buf, MAXLINE, stdin) != NULL) { Rio_writen(clientfd, buf, strlen(buf)); Rio_readlineb(&rio, buf, MAXLINE); Fputs(buf, stdout); } Close(clientfd); exit(0); }715213 Recitation C Shimin ChenEcho Client: open_clientfdint open_clientfd(char *hostname, int port) { int clientfd; struct hostent *hp; struct sockaddr_in serveraddr; if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; /* check errno for cause of error */ /* Fill in the server's IP address and port */ if ((hp = gethostbyname(hostname)) == NULL) return -2; /* check h_errno for cause of error */ bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; bcopy((char *)hp->h_addr, (char *)&serveraddr.sin_addr.s_addr, hp->h_length); serveraddr.sin_port = htons(port); /* Establish a connection with the server */ if (connect(clientfd, (SA *)&serveraddr, sizeof(serveraddr))<0) return -1; return clientfd; } This function opens a connection from the client to the server at hostname:port815213 Recitation C Shimin ChenEcho Server: Main Routineint main(int argc, char **argv) { int listenfd, connfd, port, clientlen; struct sockaddr_in clientaddr; struct hostent *hp; char *haddrp; port = atoi(argv[1]); /* the server listens on a port passed on the command line */ listenfd = open_listenfd(port); while (1) { clientlen = sizeof(clientaddr); connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET); haddrp = inet_ntoa(clientaddr.sin_addr); printf("server connected to %s (%s)\n", hp->h_name, haddrp); echo(connfd); Close(connfd); }}915213 Recitation C Shimin ChenEcho Server: open_listenfdint open_listenfd(int port) { int listenfd, optval=1; struct sockaddr_in serveraddr; /* Create a socket descriptor */ if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; /* Eliminates "Address already in use" error from bind. */ if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int)) < 0) return -1; ... (more)1015213 Recitation C Shimin ChenEcho Server: open_listenfd (cont)... /* Listenfd will be an endpoint for all requests to port on any IP address for this host */ bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons((unsigned short)port); if (bind(listenfd,(SA *)&serveraddr,sizeof(serveraddr))<0) return -1; /* Make it a listening socket ready to accept connection requests */ if (listen(listenfd, LISTENQ) < 0) return -1; return listenfd; }1115213 Recitation C Shimin ChenEcho Server: echovoid echo(int connfd) { size_t n; char buf[MAXLINE]; rio_t rio; Rio_readinitb(&rio, connfd); while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { printf("server received %d bytes\n", n); Rio_writen(connfd, buf, n); } }1215213 Recitation C Shimin ChenProxy•A proxy is an intermediary between a client and an origin server.–To the client, the proxy acts like a server.–To the server, the proxy acts like a client.EchoClientprocessEchoServerprocessEchoproxyprocess1315213 Recitation C Shimin ChenChanging ”echo” procedurevoid echo_forward(int connfd, char *server, int server_port) { int forwardfd; rio_t rio_conn, rio_forward; ssize_t n; char buf[MAXLINE]; /* connect to the server */ forwardfd = Open_clientfd(server, server_port); Rio_readinitb(&rio_forward, forwardfd); Rio_readinitb(&rio_conn, connfd); while (1) { if ((n = Rio_readlineb(&rio_conn, buf, MAXLINE)) == 0) break; Rio_writen(forwardfd, buf, n); if ((n = Rio_readlineb(&rio_forward, buf, MAXLINE)) == 0) break; Rio_writen(connfd, buf, n); } Close(forwardfd);}1415213 Recitation C Shimin ChenChanging mainint main(int argc, char **argv) { int listenfd, connfd, port, clientlen, server_port; struct sockaddr_in clientaddr; struct hostent *hp; char *haddrp, *server; port = atoi(argv[1]); server = argv[2]; server_port = atoi(argv[3]); listenfd = Open_listenfd(port); while (1) { clientlen = sizeof(clientaddr); connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen);. . . echo_forward(connfd, server, server_port); Close(connfd); } exit(0);}1515213 Recitation C Shimin ChenL7 Proxy•Different request and response
View Full Document