Introduction to Project 1 Web Client and Server
Introduction to Project 1 Web Client and Server Jan 2006
Project Goals o o Implement a simple WWW client and server Implement a tiny subset of HTTP To give you experience with HTTP and sockets programming To be familiar with Unix, Minet and prepare for the subsequent part of the project
HTTP Usage o o o HTTP is the protocol that supports communication between web browsers and web servers. Most clients/servers today use version 1. 1, but 1. 0 is also in use. HTTP protocol works on top of TCP. n n telnet www. cs. northwestern. edu 80 telnet www. ece. northwestern. edu 80
Request - Response o HTTP has a simple structure: n n client sends a request server returns a reply
HTTP request o Request-Line Headers. . . o blank line o Content. . . Request line n Method URL HTTPVersionrn Header lines Content
Four parts o o o 0: Get build, configure and run the Minet stack 1: HTTP Client 2: Connection-at-a-time HTTP Server 3: Simple select-based Multipleconnection-at-a-time server 4: Complex Select-based Multipleconnection-at-a-time Serve ( Extra Credit )
Why do we need sockets? Provides an abstraction for interprocess communication
Socket Application Network API Protocol A Protocol B o Protocol C The services (often provided by the operating system) provide the interface between application and protocol software.
Functions Define an “end- point” for communication Initiate and accept a connection Send and receive data Terminate a connection gracefully n n Examples File transfer apps (FTP), Web browsers n(HTTP), Email (SMTP/ POP 3), etc… n
Types of Sockets o o o Two different types of sockets : n stream vs. datagram Stream socket : ( a. k. a. connection- oriented socket) n It provides reliable, connected networking service n Error free; no out- of- order packets (uses TCP) n applications: telnet/ ssh, http, … Datagram socket : ( a. k. a. connectionless socket) n It provides unreliable, best- effort networking service n Packets may be lost; may arrive out of order (uses UDP) n applications: streaming audio/ video (realplayer), …
Addressing Client Server
Client – high level view Create a socket Setup the server address Connect to the server Read/write data Shutdown connection
int connect_ socket( char *hostname, int port) { Ipv 4 socket address structure int sock; struct socketaddr_in{ struct sockaddr_in sin; Hostent structure uint 8_t struct hostent{ sin_len; /*length of the structure (16)*/ struct hostent *host; sa_falimily_t sin_family /* AF_INT*/ char. STREAM, * h_name /*official name of host*/ sock = socket( AF_ INET, SOCK_ 0); in_port_t sin_port /* 16 bit TCP UDPof port number*/ char ** h_aliases; /* pointer of or array if (sock == -1) struct in_addr sin_addr /* 32 bit Ipv 4 */ pointers to address alias name*/ char sin_zero(8)/* unused*/ return sock; int h_addrtype /* host address type*/ } host = gethostbyname( hostname); int Socket(int h_length /* length of address */ family , int type, in t protocol); char ** h_addr_list /*prt to array of ptrs if (host == NULL) { return nonnegative value for OK, -1 for errorwith IPv 4 or IPv 6 address*/ close( sock); } return -1; struct hostent *gethostbyname( const char *hostname); unit 16_t htons(unit 16_t host 16 bitvaule) } /*Return nonnull if OK, error */ to /*Change the portpointer number from. NULL host on byte order memset (& sin, 0, sizeof( sin)); connect(int socketfd, const struct sockaddr * servaddr, network byte order */ sin_ family = AF_ INET; socket_t addrlen) sin_ port = htons( port); /*Perform the TCP three way handshaking*/ sin_ addr. s_ addr = *( unsigned long *) host-> h_ addr_ list[ 0]; if (connect( sock, (struct sockaddr *) &sin, sizeof( sin)) != 0) { close (sock); return -1; } return sock; } Make the socket Resolve the host Setup up the struct Connect
Server – high level view Create a socket Bind the socket Listen for connections Accept new client connections Read/write to client connections Shutdown connection
Listening on a port (TCP) int make_ listen_ socket( int port) { struct sockaddr_ in sin; int sock; sock = socket( AF_ INET, SOCK_ STREAM, 0); if (sock < 0) Make the socket return -1; memset(& sin, 0, sizeof( sin)); sin_ family = AF_ INET; Setup up the struct sin_ addr. s_ addr = htonl( INADDR_ ANY); sin_ port = htons( port); if (bind( sock, (struct sockaddr *) &sin, sizeof( sin)) < 0) Bind return -1; return sock; bind(int sockfd, const struct sockaddr * myaddr, socklen_t addrlen); } /* return 0 if OK, -1 on error assigns a local protocol adress to a socket*/
accepting a client connection (TCP) int get_ client_ socket( int listen_ socket) { struct sockaddr_ in sin; int sock; int sin_ len; memset(& sin, 0, sizeof( sin)); Setup up the struct sin_ len = sizeof( sin); sock = accept( listen_ socket, (struct sockaddr *) &sin, &sin_ len); return sock; Accept the client connection } accept(int sockefd, struct sockaddr * claddr, socklen_t * addrlen) /* return nonnegative descriptor if OK, -1 on error return the next completed connection from the front of the completed connection queue. if the queue is empty, the process is put to sleep(assuming blocking socket)*/
Sending / Receiving Data o With a connection (SOCK_STREAM): n n n int count = write(sock, &buf, len); o count: # bytes transmitted (-1 if error) o buf: char[], buffer to be transmitted o len: integer, length of buffer (in bytes) to transmit int count = read(sock, &buf, len); o count: # bytes received (-1 if error) o buf: void[], stores received bytes o len: # bytes received Calls are blocking [returns only after data is sent (to socket buf) / received]
socket() bind() TCP Client TCP Server Well-known port listen() Socket() accept() connect() Connection establishment Data(request) write() blocks until connection from client read() process request read() close() Data(reply) End-of-file no tification write() read() close()
Dealing with blocking calls o o o Many functions block n accept(), connect(), n All read() and write() For simple programs this is fine What about complex connection routines n Multiple connections n Simultaneous sends and receives n Simultaneously doing non-networking processing
Dealing with blocking (cont. . ) o Options n n n o Create multi-process or multi-threaded code Turn off blocking feature (fcntl() system call) Use the select() function What does select() do? n n n Input: a set of file descriptors Output: info on the file-descriptors’ status Therefore, can identify sockets that are “ready for use”: calls involving that socket will return immediately
select function call o int status = select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout ) n n n Status: # of ready objects, -1 if error nfds: the range of file descriptors to be checked readfds: list of descriptors to check if read-ready writefds: list of descriptors to check if write-ready errorfds: list of descriptors to check if an error conditions pending Timeout: time after which select returns
Questions? Thank you !
- Slides: 22