client-server applications approx. text coverage: chap. 21, vol iii
TRANSCRIPT
Client-Server Applications
Approx. text coverage: Chap. 21, Vol III
Copyright Rudra Dutta, NCSU, Spring, 2003 2
IntroductionTCP/IP specifies the details of how data passes between a pair of communicating applications provides peer-to-peer communication
TCP/IP standard does not… specify how to write distributed applications provide a way to start a process when a message arrives the “rendezvous” problem
Solution to rendezvous problem a program must be waiting to establish communication
before any requests arrive savings in cost scalability
Copyright Rudra Dutta, NCSU, Spring, 2003 3
Client-Server Relationship
Copyright Rudra Dutta, NCSU, Spring, 2003 4
Clients vs. ServersWho takes the first step? clients initiate peer-to-peer communications active
open servers wait for incoming communication requests
passive open
Lifetimes servers start execution before interaction begins, and
continue to accept and process requests “forever” clients are short-lived
Ports servers wait for requests at a well-known port
reserved for the service offered clients use arbitrary, non-reserved ports for
communication
Copyright Rudra Dutta, NCSU, Spring, 2003 5
Clients vs. Servers (cont’d)Complexity of clients no special privileges required (usually) overall, relatively easy to build
Complexity of servers require special system privileges (usually) may need to handle multiple requests concurrently must protect themselves against all possible errors generally more difficult to build
Both are usually implemented as application programs
Copyright Rudra Dutta, NCSU, Spring, 2003 6
Privileges and Complexity
Because of their privileged status, servers must contain code that handles...1. authentication
2. authorization
3. data security
4. privacy
5. protection (of resources)
Copyright Rudra Dutta, NCSU, Spring, 2003 7
Connectionless vs. Connection-Oriented Servers
Generally “connectionless” = UDP “connection-oriented” = TCP critical difference = level of reliability provided
Use of UDP recommended only when... application is non-critical (occasional failure is OK), or application handles reliability, or application uses hardware broadcast/multicast, or application cannot tolerate the overhead of TCP
as measured in time, and in bytes
Copyright Rudra Dutta, NCSU, Spring, 2003 8
Iterative (“one-at-a-time”) Servers…
Request handling1. wait for a client request to arrive
2. process the client request
3. send the response back to the client
4. go back to step 1
OK for services such as Echo/Time/Daytime short, single response easy to program!
But if Step 2 takes a while, other clients have to wait and/or incoming requests may be lost
Copyright Rudra Dutta, NCSU, Spring, 2003 9
…vs. Concurrent Servers“Master” process responsible for accepting requests, “Slave” processes responsible for handling requests1. Master waits for a client request to arrive
2. Master starts a new slave process to handle this request
3. Master returns to Step 1
Slave executes concurrently, terminates independently when finished
Efficient, no waiting, but harder to program
Copyright Rudra Dutta, NCSU, Spring, 2003 10
Server Deadlock ProblemServer can be subject to deadlock if... client never sends a request, server may block in a call
to read() for ever or, client sends a sequence of requests but never reads
responses What happens with UDP? TCP?
For concurrent servers, only the slave handling the request from misbehaving client will block
For single-process implementation the central server process will block will stop handling other connections Could be an issue for “apparent concurrency”
Copyright Rudra Dutta, NCSU, Spring, 2003 11
Types of Servers
Connectionless Connection-Oriented
Iterative (one-at-a-time)
Iterative Connectionless (normal UDP)
Iterative Connection-
Oriented (uncommon)
Con-current
Concurrent Connectionless
(uncommon)
Concurrent Connection-Oriented
(normal TCP)
Copyright Rudra Dutta, NCSU, Spring, 2003 12
Connection-Oriented Concurrent Server
Copyright Rudra Dutta, NCSU, Spring, 2003 13
Options for ConcurrencyDynamically create one child process per client fork() creates a child process all memory, stack, code, registers, etc. are duplicated for
the child open file and socket descriptors are shared
Dynamically create one thread per client easier to share data between clients must be careful to lock shared data structures before
modifying!
Statically create fixed number of child processes all children call accept() the next incoming connection will be handed to one child
Copyright Rudra Dutta, NCSU, Spring, 2003 14
The fork() System Callint pid;
…
pid = fork();
if (pid != 0) /* original process */
printf("The original process prints this\n");
else /* newly created process */
printf("The new process prints this\n");
•fork() returns 0 to the child process, process ID of the child to the parent process
Copyright Rudra Dutta, NCSU, Spring, 2003 15
Stateless vs. Stateful ServersServers may or may not keep state information about ongoing interactions
Keeping state information may improve efficiency smaller messages simpler processing
Keeping state also causes problems state information may become incorrect, due to
unreliable network (duplicate messages, undelivered messages)
client crashes
keeping state “bogs down” the server
Copyright Rudra Dutta, NCSU, Spring, 2003 16
Improving Server Performance
Caching in client/server interaction improves performance whenever recent history of
queries is a good indicator of future use (e.g., ARP cache)
lowers retrieval cost for all except the first request for the information
Pre-fetching of information prior to first request The “push” paradigm concurrent background processes collect and propagate
information before any program requests it wasteful if push data that no one actually needs may not be scalable
Copyright Rudra Dutta, NCSU, Spring, 2003 17
System Calls and Errors
In general, systems calls return a negative number to indicate an error servers generally add this information to a log clients generally provide some information to the user
Whenever an error occurs, system calls set the value of the global variable errno you can check errno for specific errors you can use support functions to print out or log an
ASCII text error message: perror(), strerror() windows error codes are defined at
http://www.sockets.com/err_lst1.htm
Copyright Rudra Dutta, NCSU, Spring, 2003 18
Errors (cont’d) errno is valid only after a system call has returned an error
system calls don't clear errno on success
if you make another system call you may lose the previous value of errno
extern int errno;
Copyright Rudra Dutta, NCSU, Spring, 2003 19
UDP Datagram Transmission Example
Client
Server
int value_out;
value = htonl(value);
n = write(s, (char *)&value, sizeof(value));
If (n < 0)
/* error message here */
int value_in;
n = read(s, (char *)&value_in, sizeof(value_in));
Copyright Rudra Dutta, NCSU, Spring, 2003 20
TCP Example #1: Client (fixed-length data to send)
int s, n, buflen;
char *request = "some request";
char buf[BLEN];
char *bptr;
write(s, request, strlen(request)); /* send request */
bptr = buf;
buflen = BLEN;
/* read response (may come in many pieces) */
while ((n = read(s, bptr, buflen) > 0) {
bptr += n;
buflen -= n;
}
Copyright Rudra Dutta, NCSU, Spring, 2003 21
TCP Example #2: Sending Variable-Length Messages
Client sends size of message first then sends actual data
Server receive size, then receive whole message
u_short msg_len;
Char msgout[MAXLEN];
fill_in_data(&msgout); /* make sure null-terminated */
msg_len = htons(strlen(&msgout));
write(s, (char *) &msg_len, sizeof(msg_len));/* write length */
write(s, msgout, msg_len); /* write message */
Copyright Rudra Dutta, NCSU, Spring, 2003 22
TCP Example #2 (cont’d)u_short msg_len;
char *ptr, msgin[MAXLEN];
n = 0;
ptr = (char *)&msg_len; /* read length of message */
for(i=0; i<sizeof(msg_len); i+=n, ptr+=n){
n = read(s, ptr, sizeof(msg_len)-i);
if(n < 0) /* error message here*/
}
msg_len = ntohs(msg_len);
ptr = (char *) msgin; /* now read message */
for(i=0; i<msg_len; i+=n, ptr+=n){
n = read(s, ptr, msg_len-i);
if(n < 0) /* error message here*/
}
Copyright Rudra Dutta, NCSU, Spring, 2003 23
Concurrent Server Algorithm (TCP)Master create socket and bind to well-known address for service;
leave socket unconnected place the socket in passive mode (ready for use) repeat: call accept() to receive next request from a
client, and create a slave process to handle the response
Slave receive a connection request (i.e., socket for the
connection) upon creation repeat: read request(s) from the client, and send back the
responses when finished with the client, close the connection and
exit
Copyright Rudra Dutta, NCSU, Spring, 2003 24
Server Implementationfor ( ; ; ) {
new_s = accept(s, ... ); /* blocks until connect */
/* request recv’d */
if (fork() == 0) { /* this is the child process */
close(s); /* child stops using parent’s socket */
process_request(new_s);/* get request, respond */
exit(0); /* child process is done ! */
}
close(new_s); /* this is the parent process */
/* parent stops using child’s socket */
}
Copyright Rudra Dutta, NCSU, Spring, 2003 25
Cleaning Up Child Processes
Signals = type of asynchronous interprocess communication
When a child process terminates, signal SIGCHLD is sent to the parent if the parent does not call wait() to
obtain the child's exit status, the terminating process is marked as a zombie process
the parent must call wait3() to clean up zombie processes
(see text for details)
Copyright Rudra Dutta, NCSU, Spring, 2003 26
Multiplexing with select(), again
Allows a single process to wait for connections on multiple sockets (applies to I/O in general, not just sockets)
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
struct timeval {
long tv_usec; /* seconds */
long tv_usec; /* microseconds */}
…
struct timeval max = {1,0};
Copyright Rudra Dutta, NCSU, Spring, 2003 27
select() DetailsParameters
nfds: highest number assigned to any descriptor you wish to check
readfds: set of descriptors we want to read from
writefds: set of descriptors we want to write to
exceptfds: set of descriptors to watch for exceptions
timeout: maximum time select should wait
Functions for manipulating and checking flagsFD_ZERO(fd_set *fdset) /* clear all bits in fdset */
FD_SET(int fd, fd_set *fdset) /* turn bit for fd on in fdset */
FD_CLR(int fd, fd_set *fdset) /* turn bit for fd off in fdset */
FD_ISSET(int fd, fd_set *fdset)/* test the bit for fd in fdset */
Copyright Rudra Dutta, NCSU, Spring, 2003 28
select() (cont'd)The value of the timeout argument determines the behavior of select()
NULL pointer select() returns only when one of the specified descriptors
is ready for I/O, but may wait indefinitely
Non-zero value select() returns when one of the specified descriptors is
ready for I/O but only waits up to the time specified
Zero value select() returns immediately after checking the descriptors i.e., used for polling
Copyright Rudra Dutta, NCSU, Spring, 2003 29
Using select()
1. Create fds
2. Clear fds with FD_ZERO
3. Add each descriptor you want to watch using FD_SET
4. Call select()
5. When select() returns, use FD_ISSET to see if I/O is possible • check each descriptor one-by-one
Copyright Rudra Dutta, NCSU, Spring, 2003 30
Single Process Concurrent Server Algorithm Example (TCP)
int master_s, new_s;
fd_set rfds, afds; /* read, active descriptors */
master_s = socket(...); /* create master socket */
bind(master_s, ...); /* bind to a port */
listen(master_s, 5); /* listen for requests */
FD_ZERO(&afds);
FD_SET(master_s, &afds); /* only respond to requests */
/* on master socket */
for(; ; ) {
bcopy(&rfds, &afds, sizeof(rfds));
if (select(64, &rfds, (fd_set *)0, (fd_set *)0,
(struct timeval *)0 ) < 0) /* error */
Copyright Rudra Dutta, NCSU, Spring, 2003 31
Example (cont'd)
if (FD_ISSET(master_s, &rfds)) { /* request arrived */
new_s = accept(master_s, ... );
FD_SET(new_s, &afds); /* now start listening */
} /* to the slave socket */
for(fd=0; fd < 64; fd++){ /* process slave requests */
if(fd != master_s && FD_ISSET(fd, &rfds)) {
process_request(fd);
if (finished(fd))
FD_CLR(fd, &afds);
}
}
}
Copyright Rudra Dutta, NCSU, Spring, 2003 32
Multiprotocol Servers (TCP, UDP)
Separate servers (e.g., DAYTIME) for UDP and TCP? replication of effortdifficult to maintainconsumption of resources
Multiprotocol serversbind and listen to two sockets; one for TCP,
one for UDPuse asynchronous I/O (select()) to
determine when one of the sockets needs a response
Copyright Rudra Dutta, NCSU, Spring, 2003 33
Multiservice Servers (TCP, UDP)Typically, individual server for each service dozens of server processes (daemons) routed, snmpd, in.rlogind, ftpd, mountd, telnetd, ...
Drawbacks most of the servers rarely receive requests, but
consume system resources much of the development effort is the same for
each type of server; actual request processing may be trivial
Solution: consolidate many services into a single server
Copyright Rudra Dutta, NCSU, Spring, 2003 34
Multiservice Servers (cont’d)
Server manages multiple services one port per service
UDP dedicate one port for each service handle requests in order received, iteratively
port received on identifies service needed
TCP dedicate one port per service to listen for
connection requests create a socket for each request to concurrently
handle connections
Copyright Rudra Dutta, NCSU, Spring, 2003 35
Server ConfigurationStatic configuration configuration file specifies services a server should handle to change services, change configuration file, restart server
Dynamic configuration (change services without restarting server) change configuration file, inform server server reads file, starts new services and/or terminates
services may use UNIX signals to inform server
Signal = a form of asynchronous interprocess communication (i.e., interrupts)
may use TCP/IP to inform the server Requires an extra socket
don’t terminate existing connections when reconfiguring!
Copyright Rudra Dutta, NCSU, Spring, 2003 36
inetd: the Unix Super ServerInternet services daemon – a common solution reads file /etc/inetd.conf
Opens sockets, forks processes when requests arrive uses select()to determine what needs attention without
blocking process creation overhead (has to call fork() and execve() )
inetd handles several services itself echo daytime time discard
Copyright Rudra Dutta, NCSU, Spring, 2003 37
/etc/inetd.conf File
# @(#)inetd.conf 1.24 92/04/14 SMI
#
# Configuration file for inetd(8). See inetd.conf(5).
#
# To re-configure the running inetd process, edit this
# file, then send the inetd process a SIGHUP.
#
# Internet services syntax:
# <service_name> <socket_type> <proto> <flags> <user>
# <server_pathname> <args>
# “wait” = iterative execution, “nowait” = concurrent
Copyright Rudra Dutta, NCSU, Spring, 2003 38
/etc/inetd.conf File (cont'd)
# Ftp and telnet are standard Internet services.
#
ftp stream tcp nowait root /usr/etc/in.ftpd in.ftpd
telnet stream tcp nowait root /usr/etc/in.telnetdin.telnetd
#
# Shell, login, exec, comsat and talk are BSD protocols.
#
shell stream tcp nowait root /usr/etc/in.rshd in.rshd
login stream tcp nowait root /usr/etc/in.rlogindin.rlogind
exec stream tcp nowait root /usr/etc/in.rexecd in.rexecd
comsat dgram udp wait root /usr/etc/in.comsat in.comsat
talk dgram udp wait root /usr/etc/in.talkd in.talkd
Copyright Rudra Dutta, NCSU, Spring, 2003 39
/etc/inetd.conf File (cont'd)# Finger, systat and netstat give out user information which
# may be valuable to potential "system crackers." Many sites
# choose to disable some or all of these services
# to improve security.
#
finger stream tcp nowait nobody /usr/etc/in.fingerd in.fingerd
#systat stream tcp nowait root /usr/bin/ps ps -auwwx
#netstat stream tcp nowait root /usr/ucb/netstat netstat -f inet
#
# Time service is used for clock synchronization.
time stream tcp nowait root internal
time dgram udp wait root internal
Copyright Rudra Dutta, NCSU, Spring, 2003 40
Process PreallocationMaster opens socket for well-known port creates N slaves
each inherits the socket for the well-known port
master can then exit
Each slave calls accept() when a connection request arrives, one of the slaves is
unblocked and handles the connection when finished, it closes connection and calls accept()
again
Assessment can respond quickly to short requests maximum concurrency level limited to N
Copyright Rudra Dutta, NCSU, Spring, 2003 41
Delayed Process Allocation
Tradeoff short processing time favors iterative server long processing time favors concurrent server compromise: start iteratively, switch to concurrent if
time becomes “too long”
Setting alarms system call specifies when to generate a signal to the
process
Switching from iterative to concurrent fork() creates exact duplicate of all variables,
including open sockets child process can continue from exactly the same point
Copyright Rudra Dutta, NCSU, Spring, 2003 42
Variations and ExtensionsClient Concurrency One client may communicate with multiple servers
simultaneously E.g.: make same request simultaneously to multiple servers,
so not delayed if one server is slow or unavailable
Client may receive aynsynchronous input from both a user and remote machine simultaneously
user may wish to inquire about client status, control processing, …
E.g.: telnet client
Multilevel client-server Client for one service is server for another
Powerful and broad concept