Network Programming
Network Programming
A Client-Server Transaction
Every network application is based on the client-server model:
A server process and one or more client processes Server manages some resource. Server provides service by manipulating resource for clients.
1. Client sends request Client process 4. Client handles response 3. Server sends response Server process 2. Server handles request Resource
Note: clients and servers are processes running on hosts (can be the same or different hosts).
2 15-441, Spring 2004
Page 1
Network Applications
Client Computer Client Appl. OS + Network APIs Socket Server Computer Server Appl. Socket OS + Network APIs
Network Interface OS
Internet
Network Interface OS
Network code handles issues of routing, reliability, ordering, etc. 15-441, Spring 2004
Client
Client host address 128.2.194.242 Note: 3479 is an ephemeral port allocated 4 by the kernel
Page 2
Clients
Examples of client programs
Web browsers, ftp, telnet, ssh
Client
Client
Page 3
Servers
Servers are long-running processes (daemons).
Created at boot-time (typically) by the init process (process 1) Run continuously until the machine is turned off.
Each server waits for requests to arrive on a well-known port associated with a particular service.
Port 7: echo server Port 23: telnet server Port 25: mail server Port 80: HTTP server
See /etc/services for a comprehensive list of the services available on a Linux machine.
Sockets Interface
Created in the early 80s as part of the original Berkeley distribution of Unix that contained an early version of the Internet protocols.
Page 4
Server
socket
bind
open_listenfd
open_clientfd
listen
connect
Connection request
accept
write
read
read EOF
write
close
read
close
Sockets
What is a socket?
To the kernel, a socket is an endpoint of communication. To an application, a socket is a file descriptor that lets the application read/write from/to the network.
Remember: All Unix I/O devices, including networks, are modeled as files.
Clients and servers communicate with each by reading from and writing to socket descriptors. The main distinction between regular file I/O and socket I/O is how the application opens the socket descriptors.
10
Page 5
Structure Casts
You will see a lot of structure casts
struct sockaddr_in serveraddr; /* fill in serveraddr with an address */ /* Connect takes (struct sockaddr *) as its second argument */ connect(clientfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr));
11 15-441, Spring 2004
/* /* /* /*
address family (always AF_INET) */ port num in network byte order */ IP addr in network byte order */ pad to sizeof(struct sockaddr) */
15-441, Spring 2004
Page 6
Important Functions
rio_writen(int fd, void *buf, size_t n)
Writes n bytes from buffer buf to file fd.
14
Page 7
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, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0) return -1; return clientfd; }15
15-441, Spring 2004
int clientfd;
/* socket descriptor */
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) return -1; /* check errno for cause of error */ ... (more)
16
Page 8
17
18
Page 9
20
Page 10
21
22
Page 11
24
Page 12
Were finally ready to enter the main server loop that accepts and processes client connection requests.
25 15-441, Spring 2004
26
Page 13
accept returns a connected descriptor (connfd) with the same properties as the listening descriptor (listenfd)
Returns when the connection between client and server is created and ready for I/O transfers. All I/O with the client will be done via the connected socket.
1. Server blocks in accept, waiting for connection request on listening descriptor listenfd.
listenfd(3) Server
Server connfd(4)
3. Server returns connfd from accept. Client returns from connect. Connection is now established between clientfd and connfd.
15-441, Spring 2004
Page 14
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.
29
hp = Gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr, sizeof(clientaddr.sin_addr.s_addr), AF_INET); haddrp = inet_ntoa(clientaddr.sin_addr); printf("Fd %d connected to %s (%s:%s)\n", connfd, hp->h_name, haddrp, ntohs(clientaddr.sin_port));
30
Page 15
}
31
Rio_readinitb(&rio, connfd); while((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0) { printf("server received %d bytes\n", n); Rio_writen(connfd, buf, n); Send line to } client
15-441, Spring 2004
32
Page 16
Iterative Servers
Iterative servers process one request at a time.
client 1
call connect ret connect call read ret read close call accept ret accept ret connect write call read ret read close
15-441, Spring 2004
server
call accept ret accept write close
client 2
call connect
close
33
server
call accept
client 2
User goes out to lunch Client 1 blocks waiting for user to type in data
call read
call connect
Client 2 blocks waiting to complete its connection request until after lunch!
Page 17
Concurrent Servers
Concurrent servers handle multiple requests concurrently.
client 1
call connect ret connect call fgets ret accept call read (dont block) call accept ret connect call fgets write call read write end read close
15-441, Spring 2004
server
call accept
client 2
call connect
User goes out to lunch Client 1 blocks waiting for user to type in data
35
ret accept
call read
close
Our Focus
3. Threads
Kernel automatically interleaves multiple logical flows. Each flow shares the same address space.
36
Page 18
If (a), add the new connection to the pool of connections. If (b), read any available data from the connection
Close connection on EOF and remove it from the pool.
37
select() returns the number of ready descriptors and keeps on each bit of readset for which corresponding descriptor is ready 15-441, Spring 2004
Page 19
40
Page 20
42
Page 21
for (i = 0; i < FD_SETSIZE; i++) /* Find available slot */ if (p->clientfd[i] < 0) { p->clientfd[i] = connfd; Rio_readinitb(&p->clientrio[i], connfd); FD_SET(connfd, &p->read_set); /* Add desc to read set */ if (connfd > p->maxfd) /* Update max descriptor num */ p->maxfd = connfd; if (i > p->maxi) /* Update pool high water mark */ p->maxi = i; break; } if (i == FD_SETSIZE) /* Couldn't find an empty slot */ app_error("add_client error: Too many clients"); }
43 15-441, Spring 2004
Page 22
- Significantly more complex to code than process- or thread-based designs. - Can be vulnerable to two forms of denial of service attacks
How?
45
Attack #1
Overwhelm Server with Connections
Limited to FD_SETSIZE 4 (typically 1020) connections
Defenses?
46
Page 23
server
client 2
connect
Client 2 blocks waiting to complete its connection request until after lunch!
Client gets attention of server by sending partial line Server blocks until line completed
47 15-441, Spring 2004
Flaky Client
while (Fgets(buf, MAXLINE, stdin) != NULL) { Rio_writen(clientfd, buf, strlen(buf)-1); Fgets(buf, MAXLINE, stdin); /* Read & ignore line */ Rio_writen(clientfd, "\n", 1); Rio_readlineb(&rio, buf, MAXLINE); Fputs(buf, stdout); }
Sends everything up to newline Doesnt send newline until user types another line Meanwhile, server will block
48
Page 24
49
Robust Server
/* * echoserverub.c - A robust, concurrent echo server based on select */ #include "csapp.h" typedef struct { /* represents a pool of connected descriptors */ int maxfd; /* largest descriptor in read_set */ fd_set read_set; /* set of all active descriptors */ fd_set ready_set; /* subset of descriptors ready for reading */ int nready; /* number of ready descriptors from select */ int maxi; /* highwater index into client array */ int clientfd[FD_SETSIZE]; /* set of active descriptors */ char clientbuf[FD_SETSIZE][MAXBUF]; /* set of read buffers */ int clientcnt[FD_SETSIZE]; /* Count of characters in buffers */ } pool; int byte_cnt = 0; /* counts total bytes received by server */
50
Page 25
Conceptual Model
Maintain State Machine for Each Connection
First Version: State is just identity of connfd Second Version: State includes partial line + count of characters
Design Issue
Must set granularity of state machine to avoid server blocking
52
Page 26
Complete versions of original echo client and server are developed in Computer Systems: A Programmers Perspective.
Available from csapp.cs.cmu.edu Compile and run them for yourselves to see how they work. Feel free to borrow any of this code. But be careful---it isnt sufficiently robust for our programming assignments
Most routines exit when any kind of error encountered
53 15-441, Spring 2004
Version control
Keep a clear idea of who is doing what Build program in a modular fashion Define interfaces between modules early and try not to change them too much
54 15-441, Spring 2004
Page 27
On a core (post-mortem)
gdb progname core Useful for examining program state at the point of crash
56
Page 28
print EXP
Print the value of expression Can print out values in variables
x/<count><format><size> ADDR
Examine a memory region at ADDR Count is the number of items to display (default: 1) Format is a single letter code
o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char) and s(string)
Allows multiple programmers to work on a project without accidentally editing the same file
Files must be checked out for reading or writing
If your file is called assignment1/foo.c, RCS keeps update history in assignment1/RCS/foo.c,v Current version of foo.c is maintained in foo.c,v
deltas allow retrieval of older versions
58 15-441, Spring 2004
Page 29
Can also create a blank file with rcs i mysource.c Either way, this produces version 1.1
59 15-441, Spring 2004
Note: permissions dont let us change mysource.c To change mysource.c, must acquire lock
co l mysource.c locks mysource.c so no one else can change it Use ci to check the code back in when done (adding a log message)
60 15-441, Spring 2004
Page 30
Versions
Each version of the file has a version number
release.revision format e.g. 4.2 is release 4, revision 2 Doesnt necessarily correspond to anything about real world version numbers
By default, each ci of a changed file increments revision number by 1 Can use -r flag to specify version numbers
Use this with co to retrieve old versions Use this with ci to specify what a new version should be called
Note: cant go backwards! ci r1.8 mysource.c will check in mysource.c with version number 1.8 ci r2 mysource.c will check in mysource.c with version 2.1
61 15-441, Spring 2004
More information
GDB
Official GDB homepage: http://www.gnu.org/software/gdb/gdb.html GDB primer: http://www.cs.pitt.edu/~mosse/gdb-note.html
RCS
Look at man rcs, man rcsintro Official RCS homepage:
http://www.cs.purdue.edu/homes/trinkle/RCS/
Page 31