Networking 15213-S04, Recitation, Section A Socket Socket Echo Client-Server Echo Client-Server...
-
Upload
gregory-golden -
Category
Documents
-
view
224 -
download
1
Transcript of Networking 15213-S04, Recitation, Section A Socket Socket Echo Client-Server Echo Client-Server...
NetworkingNetworking15213-S04, Recitation, Section A15213-S04, Recitation, Section A
SocketSocket
Echo Client-ServerEcho Client-Server
Extend to Echo ProxyExtend to Echo Proxy
Broken PipeBroken Pipe
– 2 – 15-213, S’04
Networking Bibles
UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI
, Prentice Hall, 1998.UNIX Network Programming, Volume 2, Second Edition: Interprocess Communications, Prentice Hall, 1999.
TCP/IP Illustrated, Volume 1: The Protocols, Addison-Wesley, 1994. TCP/IP Illustrated, Volume 2: The Implementation, Addison-Wesley, 1995.TCP/IP Illustrated, Volume 3: TCP for Transactions, HTTP, NNTP, and
the UNIX Domain Protocols, Addison-Wesley, 1996.
– 3 – 15-213, S’04
ConnectionClients and servers communicate by sending streams of bytes over
connections: point-to-point, full-duplex, and reliable
A socket is an endpoint of a connection Socket address is an IPaddress:port pair
A port is a 16-bit integer that identifies a process: well-known port: associated with some service provided by a
server (e.g., port 80 is associated with Web servers) /etc/services.global
ephemeral port: assigned automatically on client when client makes a connection request
A connection is uniquely identified by the socket addresses of its endpoints (socket pair) (cliaddr:cliport, servaddr:servport)
– 4 – 15-213, S’04
Socket
A A socketsocket is a descriptor that lets an application is a descriptor that lets an application read/write from/to the networkread/write from/to the network
Key idea: Unix uses the same abstraction for both file I/O and network I/O
Using regular Unix read and write I/O functions
Can also be used for IPC (inter-process communication)The main difference between file I/O and socket I/O is socket
family value
– 5 – 15-213, S’04
Defined in /usr/include/netinet/in.h
Internet-style sockets are characterized by a 32-bit IP address and a port
sockaddr_in
/* Internet address */struct in_addr { unsigned int s_addr; /* 32-bit IP address */ };
/* Internet style socket address */struct sockaddr_in { unsigned short int sin_family; /* Address family (AF_INET) */ unsigned short int sin_port; /* Port number */ struct in_addr sin_addr; /* IP address */ unsigned char sin_zero[...]; /* Pad to sizeof
“struct sockaddr” */};
– 6 – 15-213, S’04
Socket System Callsmust
socket() bind() listen() connect() accept() close()
socket options
ioctl() fcntl()
setsockopt() getsockopt()
gethostbyname() gethostbyaddr() getsockname()
data related
select()read() write()
send() recv()
sendto() recvfrom()
miscshutdown() socketpair() sendmsg() recvmsg()
– 7 – 15-213, S’04
EchoClient
process
EchoServer
process
1. Client sends an input line
2. Server sends the same text as it receives3. Client displays the text
it receives
A Simple C/S Application -- Echo
– 8 – 15-213, S’04
rio_readlineb
close
closeEOF
rio_readlineb
rio_writenrio_readlineb
rio_writen
listen
bind
Sequence of Socket System CallsClient Server
socket socket
acceptconnect
Connectionrequest
open_listenfd
open_clientfd
– 9 – 15-213, S’04
#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); }
Echo Client Main Routine
– 10 – 15-213, S’04
Echo 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; }
opens a connection from the client to the server at hostname:port
– 11 – 15-213, S’04
Echo 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); }}
– 12 – 15-213, S’04
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)
– 13 – 15-213, S’04
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; }
– 14 – 15-213, S’04
accept()
listenfd(3)
client
1. Server blocks in accept, waiting for connection request on listening descriptor listenfd.clientfd
server
listenfd(3)
client
clientfd
server 2. Client makes connection request bycalling and blocking in connect.
listenfd(3)
client
clientfd
server
3. Server returns connfd from accept.Client returns from connect. Connection is now established between clientfd and connfd.
connectionrequest
connfd(4)
– 15 – 15-213, S’04
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); } }
– 16 – 15-213, S’04
Echo Proxy
A A proxy proxy is an middle agent between a is an middle agent between a clientclient and an and an originorigin server. server. To the client, the proxy acts like a server. To the server, the proxy acts like a client.
EchoClient
process
EchoServer
process
EchoClient
process
EchoServer
process
Echoproxy
process
– 17 – 15-213, S’04......
rio_readlineb
rio_writen
rio_readlineb
rio_writen
listen
bind
Call Sequence in Echo ProxyClient Server
socket socket
accept
connect
rio_readlineb
...
rio_readlineb
rio_writen
listen
bind
proxy
socket
accept
connect
rio_writen
Web proxy’sbenefit
– 18 – 15-213, S’04
Changing 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);}}
– 19 – 15-213, S’04
echo_forward()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);}
– 20 – 15-213, S’04
L7 Proxy
Different request and response (HTTP)Different request and response (HTTP)
ConcurrencyConcurrency
EchoClient
process
EchoServer
process
Echoproxy
process
WebBrowserprocess
WebServer
process
Webproxy
process
– 21 – 15-213, S’04
Broken Pipe Error
When reading or writing to a socket, whose peer has When reading or writing to a socket, whose peer has already been closedalready been closed e.g. click “stop” on web browser
SIGPIPE signal and EPIPE errnoSIGPIPE signal and EPIPE errno
For example, when writing to a broken socketFor example, when writing to a broken socket For the first write, return -1 and set EPIPE For subsequent writes,
Send SIGPIPE signal, which terminates process If the signal is blocked or handled, return -1 and set EPIPE
– 22 – 15-213, S’04
How to deal with broken pipe?
Block SIGPIPE signalBlock SIGPIPE signal
Ignore EPIPE error in Rio wrappers of csapp.cIgnore EPIPE error in Rio wrappers of csapp.c
Example of how we handle broken pipe in echo serverExample of how we handle broken pipe in echo server In server main(), block SIGPIPE signal In csapp.c, ignore EPIPE error in Rio wrappers In echo(), deal with cases when return value is -1
– 23 – 15-213, S’04
Summary
SocketSocket Connection, Socket address sockaddr_in, socket system calls
Echo Client-ServerEcho Client-Server Sequence of socket system calls
Extend to Echo ProxyExtend to Echo Proxy Combine the code from both server and client
Broken PipeBroken Pipe Block SIGPIPE and ignore EPIPE