1 / 23

Recitation 15 (April 18 th )

Outline Socket programming Lab 7: Reminder Lab 7: Due next Thursday. Kun Gao kgao@cs.cmu.edu Office hours: Wednesdays 1-2PM Thursdays 2-3PM Doherty 4302D. Recitation 15 (April 18 th ). Extending echo server. Recap the echo client and server

overton
Download Presentation

Recitation 15 (April 18 th )

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Outline Socket programming Lab 7: Reminder Lab 7: Due next Thursday Kun Gao kgao@cs.cmu.edu Office hours: Wednesdays 1-2PM Thursdays 2-3PM Doherty 4302D Recitation 15 (April 18th)

  2. Extending echo server • Recap the echo client and server • Extend the echo server to build an echo proxy

  3. An echo client-server transaction 1. Client sends an input line Echo Server process Echo Client process 2. Server sends the same text as it receives 3. Client displays the text it receives

  4. bind listen Connection request connect accept rio_writen rio_readlineb Await connection request from next client rio_readlineb rio_writen EOF rio_readlineb close close Review of the sockets interface Client Server socket socket open_listenfd open_clientfd

  5. Key data structure • Defined in /usr/include/netinet/in.h /usr/include/bits/socket.h • Must cast (sockaddr_in *) to (sockaddr *) for connect, bind, and accept /* generic socket address */ struct sockaddr { unsigned short sa_family; /* protocol family */ char sa_data[14]; /* address data */ }; /* internet specific socket address */ struct sockaddr_in { unsigned short sin_family; /* address family: AF_INET) */ unsigned short sin_port; /* port number (big-endian) */ struct in_addr sin_addr; /* IP address (big-endian) */ unsigned char sin_zero[8]; /* padding */ };

  6. Echo 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); }

  7. Echo client:open_clientfd int 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:port

  8. Echo server: main routine int 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); } }

  9. Echo server: open_listenfd int 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)

  10. Echo 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; }

  11. Echo server: echo void 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); } }

  12. Echo Server process Echo Client process Proxy • A proxy is an intermediary between a client and a real server. • To the client, the proxy acts like a server. • To the server, the proxy acts like a client. Echo proxy process

  13. Change ”echo” procedure void 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); }

  14. Change main int 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); }

  15. Echo Server process Echo Client process L7 proxy • Different request and response (HTTP) • Concurrency (next recitation) • Step-by-step: • Implement sequential web proxy first Echo proxy process Web Server process Web proxy process Web Browser process

  16. HTTP request and response • An example of HTTP request and response • More details in Tuesday’s lecture

  17. HTTP request and response [kgao@bass.cmcl ~]telnet www.cs.cmu.edu 80 Trying 128.2.203.179... Connected to SUPERMAN.WEB.cmu.edu. Escape character is '^]'. GET / HTTP/1.1 Host: www.cs.cmu.edu HTTP/1.1 200 OK Date: Mon, 29 Nov 2004 00:29:22 GMT Server: Apache/1.3.31 (Unix) PHP/4.3.8 Transfer-Encoding: chunked Content-Type: text/html <HTML> <HEAD> <title> SCHOOL OF COMPUTER SCIENCE/Carnegie Mellon University </title> </HEAD> . . . . . .

  18. HTTP request Request line: <method> <uri> <version> GET / HTTP/1.1 Host: www.cs.cmu.edu Request headers: <header name>: <header data> ‘\r\n’ to mark the end of the request <url>: Uniform Resource Locator E.g. http://hostname:8080/path/to/the/resource <uri>: Uniform Resource Identifier: suffix of url E.g. /path/to/the/resources Complete URL is used if sending request to proxy

  19. HTTP response Response line: <version> <status code> <status msg> Response headers: <header name>: <header data> HTTP/1.1 200 OK Date: Mon, 29 Nov 2004 00:29:22 GMT Server: Apache/1.3.31 (Unix) PHP/4.3.8 Transfer-Encoding: chunked Content-Type: text/html <HTML> <HEAD> <title> SCHOOL OF COMPUTER SCIENCE/Carnegie Mellon University </title> </HEAD> . . . . . . ‘\r\n’ Response body: Web page

  20. Web proxy in Lab 7 GET http://www.cmu.edu:80/index.html HTTP/1.0 <other information> Web Browser process Web proxy process Web Server process Connects to the target web server, sends request looking like this: GET /index.html HTTP/1.0 <other information in the original request> Lab 7 things to-do: parse HTTP request (1st line): extract hostname & port number port is not necessarily specified in the request if the default number is used (80) The web proxy simply forwards the response from the server to the browser

  21. Broken pipe error • When writing to a socket whose connection has been closed prematurely at the other end • e.g. click “stop” on web browser • For the first write, return normally • For subsequent writes • Send SIGPIPE signal, which terminates process by default • If SIGPIPE is blocked or caught, return -1 & set EPIPE. • We don’t want to terminate the web proxy • Handle this error gracefully …

  22. How to deal with broken pipe? • Block or ignore SIGPIPE signal • Signal(SIGPIPE, SIG_IGN) • Ignore EPIPE error in Rio wrappers in csapp.c • Example of how we handle broken pipe in echo proxy • In server main(), we block SIGPIPE signal • In csapp.c, we ignore EPIPE error in Rio wrappers

  23. Some other hints • Port number ./port_for_user.pl <your andrew id> • For initial debugging • use telnet; use lots of print statements • Test with real Internet browser: set proxy server • Use RIO package for all I/O on sockets • A lot of helper functions and wrappers in csapp.c

More Related