Sogang University
Network Programming: Part II
CSE4100: System Programming
Youngjae Kim (PhD)
Copyright By PowCoder代写 加微信 powcoder
https://sites.google.com/site/youkim/home
Distributed Computing and Operating Systems Laboratory (DISCOS)
https://discos.sogang.ac.kr
Office: R911, E-mail:
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
2. Start client Client
getaddrinfo socket
1. Start server Server
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
rio_writen rio_readlineb rio_readlineb rio_writen
Client / Server Session
3. Exchange data
Await connection request from next client
4. Disconnect client
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb
5. Drop client
Sogang University
getaddrinfo
getaddrinfo
bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Interface: socket
¡é Clients and servers use the socket function to create a socket descriptor:
int socket(int domain, int type, int protocol)
¡é Example:
int clientfd = Socket(AF_INET, SOCK_STREAM, 0);
Indicates that we are using Indicates that the socket 32-bit IPV4 addresses will be the end point of a
connection
Protocol specific! Best practice is to use getaddrinfo to generate the parameters automatically, so that code is protocol independent.
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
getaddrinfo socket
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Interface: bind
¡é A server uses bind to ask the kernel to associate the
server¡¯s socket address with a socket descriptor:
int bind(int sockfd, SA *addr, socklen_t addrlen);
¡é The process can read bytes that arrive on the connection whose endpoint is addr by reading from descriptor sockfd.
¡é Similarly, writes to sockfd are transferred along connection whose endpoint is addr.
Best practice is to use getaddrinfo to supply the arguments addr and addrlen.
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
getaddrinfo socket
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Interface: listen
¡é By default, kernel assumes that descriptor from socket function is an active socket that will be on the client end of a connection.
¡é A server calls the listen function to tell the kernel that a descriptor will be used by a server rather than a client:
int listen(int sockfd, int backlog);
¡é Converts sockfd from an active socket to a listening socket that can accept connection requests from clients.
¡é backlog is a hint about the number of outstanding
connection requests that the kernel should queue up
before starting to refuse requests.
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
getaddrinfo socket
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Interface: accept
¡é Servers wait for connection requests from clients by
calling accept:
int accept(int listenfd, SA *addr, int *addrlen);
¡é Waits for connection request to arrive on the connection bound to listenfd, then fills in client¡¯s socket address in addr and size of the socket address in addrlen.
¡é Returns a connected descriptor that can be used to communicate with the client via Unix I/O routines.
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
getaddrinfo socket
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Interface: connect
¡é A client establishes a connection with a server by calling connect:
int connect(int clientfd, SA *addr, socklen_t addrlen);
¡é Attempts to establish a connection with server at socket address addr
¡ì If successful, then clientfd is now ready for reading and writing. ¡ì Resulting connection is characterized by socket pair
(x:y, addr.sin_addr:addr.sin_port)
¡ì x is client address
¡ì y is ephemeral port that uniquely identifies client process on client host
Best practice is to use getaddrinfo to supply the arguments addr and addrlen.
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
accept Illustrated listenfd(3)
1. Server blocks in accept, waiting for connection request on listening descriptor listenfd
2. Client makes connection request by calling and blocking in connect
Connection request
listenfd(3)
listenfd(3)
3. Server returns connfd from accept. Client returns from connect.
Connection is now established between clientfd and connfd
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Connected vs. Listening Descriptors
¡é Listening descriptor
¡ì End point for client connection requests
¡ì Created once and exists for lifetime of the server
¡é Connected descriptor
¡ì End point of the connection between client and server
¡ì A new descriptor is created each time the server accepts a connection request from a client
¡ì Exists only as long as it takes to service client ¡é Why the distinction?
¡ì Allows for concurrent servers that can communicate over many client connections simultaneously
¡ì E.g., Each time we receive a new request, we fork a child to handle the request
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
getaddrinfo socket
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
getaddrinfo
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Helper: open_clientfd ¡é Establish a connection with a server
int open_clientfd(char *hostname, char *port) { int clientfd;
struct addrinfo hints, *listp, *p;
/* Get a list of potential server addresses */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* Open a connection */ hints.ai_flags = AI_NUMERICSERV; /* …using numeric port arg. */ hints.ai_flags |= AI_ADDRCONFIG; /* Recommended for connections */ Getaddrinfo(hostname, port, &hints, &listp);
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Sockets Helper: open_clientfd (cont)
/* Walk the list for one that we can successfully connect to */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((clientfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) < 0) continue; /* Socket failed, try the next */
/* Connect to the server */
if (connect(clientfd, p->ai_addr, p->ai_addrlen) != -1) break; /* Success */
Close(clientfd); /* Connect failed, try another */ }
/* Clean up */
Freeaddrinfo(listp);
if (!p) /* All connects failed */
return -1;
else /* The last connect succeeded */
return clientfd;
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
getaddrinfo socket
getaddrinfo socket bind listen
Sockets Interface
open_listenfd
open_clientfd
Connection request
Client / Server Session
Await connection request from next client
rio_writen rio_readlineb rio_readlineb rio_writen
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
rio_readlineb close
Sogang University
Sockets Helper: open_listenfd
¡é Create a listening descriptor that can be used to accept
connection requests from clients.
int open_listenfd(char *port) {
struct addrinfo hints, *listp, *p; int listenfd, optval=1;
/* Get a list of potential server addresses */
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_socktype = SOCK_STREAM; /* Accept connect. */ hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; /* …on any IP addr */ hints.ai_flags |= AI_NUMERICSERV; /* …using port no. */ Getaddrinfo(NULL, port, &hints, &listp);
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Sockets Helper: open_listenfd (cont)
/* Walk the list for one that we can bind to */
for (p = listp; p; p = p->ai_next) {
/* Create a socket descriptor */
if ((listenfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) < 0) continue; /* Socket failed, try the next */
/* Eliminates "Address already in use" error from bind */
Setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
/* Bind the descriptor to the address */
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break; /* Success */
Close(listenfd); /* Bind failed, try the next */ }
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Sockets Helper: open_listenfd (cont)
/* Clean up */
Freeaddrinfo(listp);
if (!p) /* No address worked */
return -1;
/* Make it a listening socket ready to accept conn. requests */
if (listen(listenfd, LISTENQ) < 0) { Close(listenfd);
return -1;
return listenfd;
¡é Key point: open_clientfd and open_listenfd are both independent of any particular version of IP.
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Echo Client: Main Routine
#include "csapp.h"
int main(int argc, char **argv) {
int clientfd;
char *host, *port, buf[MAXLINE]; rio_t rio;
host = argv[1];
port = 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);
echoclient.c
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Iterative Echo Server: Main Routine
#include "csapp.h¡± void echo(int connfd);
int main(int argc, char **argv) {
int listenfd, connfd;
socklen_t clientlen;
struct sockaddr_storage clientaddr; /* Enough room for any addr */ char client_hostname[MAXLINE], client_port[MAXLINE];
listenfd = Open_listenfd(argv[1]); while (1) {
clientlen = sizeof(struct sockaddr_storage); /* Important! */ connfd = Accept(listenfd, (SA *)&clientaddr, &clientlen); Getnameinfo((SA *) &clientaddr, clientlen,
client_hostname, MAXLINE, client_port, MAXLINE, 0); printf("Connected to (%s, %s)\n", client_hostname, client_port); echo(connfd);
Close(connfd);
exit(0); }
echoserveri.c
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
Sogang University
Echo Server: echo function
¡é The server uses RIO to read and echo text lines until EOF (end-of-file) condition is encountered.
¡ì EOF condition caused by client calling close(clientfd)
void echo(int connfd) {
char buf[MAXLINE]; rio_t rio;
Rio_readinitb(&rio, connfd);
while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) {
printf("server received %d bytes\n", (int)n); Rio_writen(connfd, buf, n);
Bryant and O¡¯Hallaron, Computer Systems: A Programmer¡¯s Perspective, Third Edition
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com