tdc561 network programming week 4: client/server design approaches case study using sockets – a...
Post on 19-Dec-2015
217 views
TRANSCRIPT
TDC561 Network Programming
Week 4: Client/Server Design Approaches
Case Study Using Sockets – A Client Server Application of Network Performance Management
presentation prepared with the help of Dale Knudson PhD, Lucent Technologies
Network Programming (TDC561) Page 2Winter 2003
References
Douglas Comer, David Stevens, Internetworking with TCP/IP : Client-Server Programming, Volume III (BSD Unix and ANSI C), 2nd edition, 1996 (ISBN 0-13-260969-X) – Chap. 2, 8
W. Richard Stevens, Network Programming : Networking API: Sockets and XTI, Volume 1, 2nd edition, 1998 (ISBN 0-13-490012-X) – Chap. 7 (partial), 27 (partial), 16.1-16.3 (partial)
Network Programming (TDC561) Page 3Winter 2003
Server Design
IterativeIterativeConnectionlessConnectionless
IterativeIterativeConnection-OrientedConnection-Oriented
ConcurrentConcurrentConnection-OrientedConnection-Oriented
ConcurrentConcurrentConnectionlessConnectionless
Network Programming (TDC561) Page 4Winter 2003
Concurrent vs. Iterative
Iterative
•Small, fixed size requests•Easy to program
Iterative
•Small, fixed size requests•Easy to program
Concurrent
•Large or variable size requests•Harder to program•Typically uses more system resources
Concurrent
•Large or variable size requests•Harder to program•Typically uses more system resources
Network Programming (TDC561) Page 5Winter 2003
Connectionless vs. Connection-Oriented
Connection-Oriented
•Easy to program•Transport protocol handles the tough stuff.•Requires separate socket for each connection.
Connection-Oriented
•Easy to program•Transport protocol handles the tough stuff.•Requires separate socket for each connection.
Connectionless
•Less overhead•No limitation on number of clients
Connectionless
•Less overhead•No limitation on number of clients
Network Programming (TDC561) Page 6Winter 2003
Statelessness
State: Information that a server maintains about the status of ongoing client interactions.
Issues with Statefullness Issues with Statefullness – Clients can go down at any time.Clients can go down at any time.
– Client hosts can reboot many times.Client hosts can reboot many times.
– The network can lose messages.The network can lose messages.
– The network can duplicate messages.The network can duplicate messages.
ExampleExample– Connectionless servers that keep state information must be
designed carefully
» Messages can be duplicatedMessages can be duplicated
Network Programming (TDC561) Page 7Winter 2003
Concurrent Server Design Alternatives
One child per client
Single Process Concurrency (AKA Pseudo-Concurrency or
Apparent Concurrency)
Pre-forking multiple processes
Spawn one thread per client
Pre-threaded Server
will be discussed in a future lecture
Network Programming (TDC561) Page 8Winter 2003
One child per client
Traditional Unix server:
– TCP: after call to accept(), call fork().
– UDP: after recvfrom(), call fork().
– Each process needs only a few sockets.
– Small requests can be serviced in a small amount of time.
Parent process needs to clean up after children (call wait() ).
Network Programming (TDC561) Page 9Winter 2003
Discussion Stevens Example: Concurrency using fork() 1/3
/* Code fragment that uses fork() and signal()
to implement concurrency */
/* include and define statements section */
void signal_handler(int sig) {
int status;
wait(&status); /* awaits child process to exit
therefore allows child to terminate,
and to transit from ZOMBIE to
NORMAL TEMINATION (END) state
*/
signal(SIGCHLD,&signal_handler);
/* restarts signal handler */
}
Network Programming (TDC561) Page 10Winter 2003
Discussion Stevens Example: Concurrency using fork() 2/3
main(int argc, char *argv[]){/* Variable declaration section *//* The calls socket(), bind(), and listen() */
signal(SIGCHLD,&signal_handler);while(1) { /* infinite accept() loop */newfd = accept(sockfd,(struct sockaddr *)&theiraddr,&sinsize);if (newfd < 0) { /* error in accept() */if (errno = EINTR)
continue;else {
perror("accept");exit(-1);
}}
See previous slide
Network Programming (TDC561) Page 11Winter 2003
Discussion Stevens Example: Concurrency using fork() 3/3
/* successfully accepted a new client connection newfd >=0 */
switch (fork()) {
case -1: /* fork() error */
perror("fork");
exit(-1);
case 0: /* child handles request */
close(sockfd);
/* read msg and form a response */
/* send response back to the client */
close(newfd);
exit(-1); /* exit() sends by default SIGCHLD to parent */
default: /* parent returns to wait for another request */
close(newfd);
} /* end switch */
} /* end while(1) */
}
Network Programming (TDC561) Page 12Winter 2003
Discussion: Single Process Concurrency 1/2
main(int argc, char *argv[]){/* various declarations */int result;fd_set readfds, testfds;/* socket(), bind(), listen() … *//* inititialization of the fd setFD_ZERO(&readfds);/* add listening socket sockfd to the reading set */FD_SET(sockfd,&readfds);while(1) {int fd;testfds = readfds;result = select(FD_SETSIZE, &testfds, NULL, NULL, NULL);/* error check for select */
Network Programming (TDC561) Page 13Winter 2003
Discussion: Single Process Concurrency 2/2
for (fd = 0; fd < FD_SETSIZE; fd++) {
if (FD_ISSET(fd,&testfds)) { /* find activated socket fd */
if (fd == sockfd) { /* ==> New connection */
newfd = accept(sockfd,(struct sockaddr *)&theiraddr,&sinsize);
FD_SET(newfd,&readfds); /* update file descriptor set with newfd */
}
else { /* ==> request from ``old'' connection */
/* call read() and handle request
from old connection using fd */
close(fd);
FD_CLR(fd,&readfds); /* remove fd when connection finished */
} /* else */
} /* end if (FD_ISSET() */
} / * end for (; ; ) */
} /* end while(1) */
return 1;
}
Network Programming (TDC561) Page 14Winter 2003
OAM&P - Operations, Administration, Maintenance and Provisioning
ITU Categories
(International Telecommunications Union)
1. Configuration Management (CM)
2. Accounting Management (AM)
3. Fault Management (FM)
4. Performance Management (PM)
5. Security Management (SM)
Network Programming (TDC561) Page 15Winter 2003
Performance Management
Wireless SwitchOSS
NM
PM report
(one per hour)
ftp
What if you want the data more frequently?
Custom
Reports
OSS NM – Operation Support System - Network Manager
Network Programming (TDC561) Page 16Winter 2003
OMP Server
Every 5 minutes
(but how much data?)
Collection
Specification OMP
Part A – every 1 hour
Part B – every 30 minutes
Part C – every 5 minutes
OMP Server (Operations and Maintenance Platform Server)
Network Programming (TDC561) Page 21Winter 2003
OMP
Web browser
Ethernet
Web Server
HTML
pages
PM hourly
data
CGI Script
Generated
HTML
Network Programming (TDC561) Page 22Winter 2003
OMP
Web browser
Ethernet
Web Server
HTML
pages
PM hourly
data
CGI Script
Generated
HTML
PM On
Demand data
Network Programming (TDC561) Page 23Winter 2003
OMP
Web browser
Ethernet
Web Server
HTML
pages
PM hourly data
CGI Script
Generated
HTML
On Demand data
PM
Hourly
Collection
PM
On Demand
Collection
Network Programming (TDC561) Page 24Winter 2003
OMP
User Terminal
Ethernet
Web Server
HTML
pages
PM hourly data
CGI Script
Generated
HTML
On Demand data
PM
Hourly
Collection
PM
On Demand
Collection
Web Browser
Java applet
Network Programming (TDC561) Page 25Winter 2003
OMP
User Terminal
Ethernet
Web Server
HTML
pages
PM hourly data
CGI Script
Generated
HTML
On Demand data
PM
Hourly
Collection
PM
On Demand
Collection
Server
Web Browser
Java applet
Client
Socket
Network Programming (TDC561) Page 26Winter 2003
On Demand
Collection
(server socket)
CREATE A SERVER SOCKET
AF_INET = use TCP/IP internet protocols
SOCK_STREAM = connection oriented socket (not datagrams)
s_sock = socket( AF_INET, SOCK_STREAM, 0)
Note that this socket is not yet associated with a
port number.
Network Programming (TDC561) Page 27Winter 2003
On Demand
Collection
(server socket)
CREATE A SERVER SOCKET
s_sock = socket( AF_INET, SOCK_STREAM,0)
bind will associate s_sock with a local name or address/port pair.
memset(&serv_adr, 0, sizeof(serv_adr));
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = INADDR_ANY;
serv_adr.sin_port = htons(PORT);
bind (s_sock, (struct sockaddr *)(&serv_adr), sizeof(serv_adr));
Note that this port number will be known to all the clients.
Network Programming (TDC561) Page 28Winter 2003
On Demand
Collection
(server socket)
CREATE A SERVER SOCKET
s_sock = socket( AF_INET, SOCK_STREAM,0)
bind (s_sock, (struct sockaddr *)(&serv_adr), sizeof(serv_adr));
Set up a queue for incoming connection requests.
In this case set up for a maximum of 5 clients.
listen (s_sock, 5);
Network Programming (TDC561) Page 29Winter 2003
Java applet
(socket client)
CREATE A CLIENT SOCKET
AF_INET = use TCP/IP internet protocols
SOCK_STREAM = connection oriented socket (not datagrams)
c_sock = socket( AF_INET, SOCK_STREAM, 0)
Note that this socket is not yet associated with a
local or destination address.
Network Programming (TDC561) Page 30Winter 2003
Java applet
(socket client)
CREATE A CLIENT SOCKET
c_sock = socket( AF_INET, SOCK_STREAM,0);
Connect binds a permanent destination to a socket, placing it in the connected state.
Internet address interpretation routine – translates from dotted decimal format (e.g., a.b.c.d) to a 32 bit internet address.
serv_adr.sin_family = AF_INET;
serv_adr.sin_addr.s_addr = inet_addr(serv_address);
serv_adr.sin_port = htons(PORT);
connect (c_sock, (*sockaddr *)&server, sizeof(server));
Network Programming (TDC561) Page 31Winter 2003
Java applet
(socket client)
CREATE A CLIENT SOCKET
c_sock = socket( AF_INET, SOCK_STREAM,0);
connect (c_sock, (*sockaddr *)&server, sizeof(server));
The client can now start reading and writing on the socket.
Do {
buf = message to send to the server
write (c_sock, buf, len);
read (c_sock, buf, len);
process response message received from the server
} while (1); /* or until complete */
Network Programming (TDC561) Page 32Winter 2003
On Demand
Collection
(socket server)
Java applet
(socket client)
Known port
number
Network Programming (TDC561) Page 33Winter 2003
On Demand
Collection
(server socket)
CREATE A SERVER SOCKET
s_sock = socket( AF_INET, SOCK_STREAM,0)
bind (s_sock, (struct sockaddr *)(&serv_adr), sizeof(serv_adr));
listen (s_sock, 5);
Once a socket has been set up, the server needs to wait for a connection. To do so, it uses system call accept. A call to accept blocks until a connection request arrives.
do {
new_sock = accept (s_sock, (struct sockaddr *) &client_adr, &client_len);
if (fork() == 0) { /* in CHILD process */
while ((len=read(new_sock, buf, size)){
/* process message */
} close (new_sock); exit(0);
} else close (new_sock); /* in parent */
} while (1); /* process messages forever */
Network Programming (TDC561) Page 34Winter 2003
On Demand
Collection
(server socket)
CREATE A SERVER SOCKET
s_sock = socket( AF_INET, SOCK_STREAM,0)
bind (s_sock, (struct sockaddr *)(&serv_adr), sizeof(serv_adr));
listen (s_sock, 5);
new_sock = accept (s_sock, (struct sockaddr *) &client_adr, &client_len);
When a request arrives, the system fills in client_adr with the address of the client that placed the request.
The system creates a new socket file descriptor, new_sock, that has its destination connected to the requesting client.
Network Programming (TDC561) Page 35Winter 2003
On Demand
Collection
(socket server)
Java applet
(socket client)
Active socket
(returned by accept)
When the server accepts a connection from a client, a new file descriptor is assigned.
Known port Number
Listening/
Passive socket
Network Programming (TDC561) Page 36Winter 2003
On Demand
Collection
(socket server)
Java applet
(socket client)
Known port
number
Second Client
Network Programming (TDC561) Page 43Winter 2003
Question: How can we have a single process handle all the client interfaces and at the same time do all PM count retrieval from the cells?
Why would we want to do this?
Network Programming (TDC561) Page 44Winter 2003
void ODinit()
{
/* Call the signal handler if we get one a SIGPOLL signal. This indicates that
** a socket needs servicing.
*/
(void) sigset (SIGPOLL, odsig_handler);
--- continued later ---
}
static void ODsig_handler (int sig)
{
switch (sig) {
case SIGPOLL:
sigpoll_flag = TRUE;
default: break;
}
}
Network Programming (TDC561) Page 45Winter 2003
main ( )
{ /* On Demand collection process */
ODinit(); /* initialize the socket *
while (1) {
while (ODwork_to_do()){
ODdo_work();
}
ODwait_for_work();
}
}
Network Programming (TDC561) Page 46Winter 2003
Void ODwait_for_work ( void ) /* Define how to react to Asynchronous Events - messages */
{ uxretval = UXWGETMSG ( &uxmbuf, UXFOREVER );
switch ( uxretval) {
case UXMSG: /* Process the UXMSG received from a cell - Network Element */
ODuxmsg(&uxmbuf );
break;
case UXEINTR: /* Got an interrupt.
Handled on return from this function */
break;
case UXENOPORT: /* Somehow the port we are doing
the UXWGETMSG on got dropped */
/* Restart the Unix port */
uxretval = UXCONNPORT(ITPT_OD);
break;
default: break;
}
}
Network Programming (TDC561) Page 47Winter 2003
int ODwork_to_do (void)
{
if (cl1timerflag || cl2timerflag || … )
return (TRUE);
if (rsp1timerflag || rsp2timerflag || … )
return (TRUE);
if (sigpoll_flag)
return (TRUE);
return (FALSE);
}
Network Programming (TDC561) Page 48Winter 2003
Void ODdo_work ( void ) {
if (sigpoll_flag) { /* Process client request */
sigpoll_flag = FALSE;
ODclient_req(); remember this one
}
if (cl1timerflag) { /* Process periodic request to Network elements (cells, ..)*/
ODmsgdest (ODCL1TIMERTAG);
odcl1timerflag = FALSE;
}
if (rsp1timerflag) { /* Timed out waiting for response from Network elements (cells, ..)*/
ODerr(ODRSP1TIMERTAG);
ODRSP1TIMERTAG = FALSE;
}
if (audit_timer_flag) { /* Time for a socket audit */
ODsock_audit();
}
}
Network Programming (TDC561) Page 49Winter 2003
ODinit continued
Void ODinit ()
{
/* Initialize the server structure */
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
/* Get the service port associated with this process
usually in some /etc/ config file such as /etc/services */
servent_p = getservbyname ( PMSERVICE, “tcp” ); /* NOTE: API is not IPv6 compliant!*/
server.sin_port = servent_p->s_port;
/* Now create the connection socket */
ODsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/* Allow local address reuse */
on = 1;
setsockopt (ODsock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
Network Programming (TDC561) Page 50Winter 2003
ODinit continued
Void ODinit ()
{
/* Bind the socket to the local address specified on the server.
This establishes a local address for the socket. */
bind (ODsock, (struct sockaddr *) (&server), sizeof(server));
/* Set up the server to listen for connection requests from the client.
This simply marks the socket as ready to receive a connection.
It does not wait for the client to connect. */
(void) listen (ODsock, 10); /* allow 10 connections pending */
Network Programming (TDC561) Page 52Winter 2003
X X X
X X X X X
select() says these file descriptors from the ODreadmask have work pending
ODreadmask Set by FD_SET
FD_ISSET – tells if a particular file descriptor returned by select() has pending work
Network Programming (TDC561) Page 53Winter 2003
ODinit continued
Void ODinit ()
{
/* Include the socket descriptor in the list of sockets to poll. Set up
the descriptor so that we get a SIGPOLL when there’s something
to read from the socket. */
FD_ZERO (&ODreadmask);
FD_SET (ODsock, &ODreadmask);
if ( (rc -= ioctl (ODsock, I_SETSIG, S_INPUT )) == -1 ) {
error
}
/* At this point, if we get any input requests on the connection server
socket, we’ll get a SIGPOLL, call our sigpoll handler, and set a flag
indicating that we have input on one of our sockets.
*/
Network Programming (TDC561) Page 54Winter 2003
Void ODclient_req ( void )
{
/* ODreadmask is a global file descriptor set. Initially it includes only the
bound (listening) socket file descriptor. New file descriptors are added to the
ODreadmask after accepting a connection request.
Since select() modifies the read mask, we’ll have to make a copy. */
memcpy (&readfdset, &ODreadmask, sizeof(readfdset));
/* select() is used to determine if there are outstanding requests at
any of the socket fds */
numrequests = select (nfds, &readfdset, (fd_set *)NULL,
(fd_set *)NULL, &timeout);
Network Programming (TDC561) Page 55Winter 2003
ODclient continued
/* Loop through all the client socket file descriptors to determine
the next socket with an outstanding request. */
for (i = 0; i < nfds; i++) {
if (!FD_ISSET (socknum, &readfdset) {
/* nothing for this fd */
return;
}
/* If the request is from the listening socket, do an
accept and add the new socket file descriptor to the global readmask.
otherwise we have work for a client already connected. */
if (socknum == ODsock) {
ODconnect_client(); /* New client */
} else { ODapi (socknum); }
}
Network Programming (TDC561) Page 56Winter 2003
Void ODconnect_client ( void )
{
/* accept() will extract the first connection on the queue of pending
connections, create a new socket with the properties of ODsock,
and allocate a new file descriptor (clientsock) for the socket. */
clientsock = accept (ODsock, (struct sockaddr *)0, &i );
/* set up this socket so that it generates a SIGPOLL when it has input */
rc = ioctl (clientsock, I_SETSIG, S_INPUT);
/* Add the socket to the global read mask */
FD_SET ( clientsock, &ODreadmask );
/* We have a valid client. Send a challenge message to the client. */
ODsendchallenge ( clientsock, challenge_type );
}
Network Programming (TDC561) Page 57Winter 2003
Void ODsock_audit ()
{
/* Loop through connection table - list of all active socket file desriptors*/
/* If fd is open, but no activity for two intervals, close the socket */
ODclose_sock ( ODconnect[i], sockfd );
/* Reset the audit timer */
UXTIMER(intvl, AUDIT_TAG, ODtimer_exp);
}
Network Programming (TDC561) Page 58Winter 2003
Java applet – client side
public void run() {
// open a socket to the server
sock.open(hostName, portNo);
}
class PModSW {
public int open(String hostName, int portNo)
{
sock = new Socket(hostName, portNo)
// getInputStream is the input stream for reading bytes from the
// DataInputStream
sockIn = new DataInputStream(sock.getInputStream());
//getOutputStream writes to the DataOutputstream
sockOut = new DataOutputStream (sock.getOutputStream());
}
Network Programming (TDC561) Page 59Winter 2003
Java applet – client side continued
public String getLine()
{
// read response message from the OMP,
// waits until a message is received
line = sockIn.readLine();
}
public int sendReq (byte[] msg, int offset, int length)
{
// send a message to the server on the OMP
sockOut.write (msg, offset, length)
}
} // end of PModSW class
Network Programming (TDC561) Page 61Winter 2003
Socket Options
Various attributes that are used to determine the behavior of sockets.
Setting options tells the OS/Protocol Stack the behavior we want.
Support for generic options (apply to all sockets) and protocol specific options.
Network Programming (TDC561) Page 62Winter 2003
Setting and Getting option values
getsockopt() gets the current value of a socket option.
setsockopt() is used to set the value of a socket option.
#include <sys/socket.h>
Network Programming (TDC561) Page 63Winter 2003
int getsockopt( int sockfd,
int level,
int optname,
void *opval,
socklen_t *optlen);
level specifies whether the option is a general option or a protocol specific option (what level of code should interpret the option).
getsockopt()
Network Programming (TDC561) Page 64Winter 2003
int setsockopt( int sockfd,
int level,
int optname,
const void *opval,
socklen_t optlen);
setsockopt()
Network Programming (TDC561) Page 65Winter 2003
SO_REUSEADDR
Boolean option: enables binding to an address (port) that is already in use.
Used by servers that are transient - allows binding a passive socket to a port currently in use (with active sockets) by other processes.
Can be used to establish separate servers for the same service on different interfaces (or different IP addresses on the same interface).
Virtual Web Servers can work this way.
Network Programming (TDC561) Page 66Winter 2003
Signal Driven I/O (R. Stevens, text, chap.22 )
A signal handler can be installed to instruct the kernel to generate a SIGIO or SIGPOLL signal whenever something happens to a socket descriptor.
The signal handler must determine what conditions caused the signal and take appropriate action.
See also Stevens, sect. 7.10 – fcntl (SVR4) and ioctl(BSDx) and fcntl (POSIX)
Network Programming (TDC561) Page 67Winter 2003
Signal Driven UDP
SIGIO occurs whenever:– an incoming datagram arrives.
– an asynchronous error occurs.
» such as unreachable or invalid address
Could allow process to handle other tasks and still watch for incoming UDP messages.
Example of signal-driven UDP example described in the book ( R. Stevens, text, chap.22):– NTP Network Time Protocol.
– Used to record timestamp of arrival of UDP datagram.
Network Programming (TDC561) Page 68Winter 2003
Signal Driven TCP
SIGIO occurs whenever:– an incoming connection has completed.
– Disconnect request initiated.
– Disconnect request completed.
– Half a connection shutdown.
– Data has arrived.
– Data has been sent (indicating there is buffer space)
– Asynchronous error