Socket Programming Issues

Download Report

Transcript Socket Programming Issues

Lecture 4
Socket Programming Issues
CPE 401 / 601
Computer Network Systems
slides
modified
from
Dave
Hollinger
slides
are are
modified
from
Dave
Hollinger
Debugging
• Debugging can be difficult
• Write routines to print out sockaddrs
• Use trace, strace, ptrace, truss, etc
• Include code that can handle unexpected
situations
CPE 401/601 Lecture 4 : Socket Programming Issues
2
Timeout when calling recvfrom()
• It might be nice to have each call to recvfrom()
return after a specified period of time even if
there is no incoming datagram
• We can do this by using SIGALRM and
wrapping each call to recvfrom() with a call to
alarm()
There are some other
(better) ways to do this
CPE 401/601 Lecture 4 : Socket Programming Issues
3
UDP Connected mode
• A UDP socket can be used in a call to connect()
• This simply tells the O.S. the address of the
peer
• No handshake is made to establish that the
peer exists
• No data of any kind is sent on the network as
a result of calling connect() on a UDP socket
CPE 401/601 Lecture 4 : Socket Programming Issues
4
Connected UDP
• Once a UDP socket is connected:
– can use sendto() with a null dest address
– can use write() and send()
– can use read() and recv()
• only datagrams from the peer will be returned
– Asynchronous errors will be returned to the
process
OS Specific, some won’t do this!
CPE 401/601 Lecture 4 : Socket Programming Issues
5
Asynchronous Errors
• What happens if a client sends data to a
server that is not running?
– ICMP “port unreachable” error is generated by
receiving host and sent to sending host
– The ICMP error may reach the sending host after
sendto() has already returned!
– The next call dealing with the socket could return
the error
CPE 401/601 Lecture 4 : Socket Programming Issues
6
Back to UDP connect()
• Connect() is typically used with UDP when
communication is with a single peer only
• It is possible to disconnect and connect the
same socket to a new peer
– More efficient to send multiple datagrams to the
same user
• Many UDP clients use connect()
• Some servers (TFTP)
CPE 401/601 Lecture 4 : Socket Programming Issues
7
I/O Multiplexing
I/O Multiplexing
• We often need to be able to monitor multiple
descriptors:
– a generic TCP client (like telnet)
– a server that handles both TCP and UDP
– Client that can make multiple concurrent requests
• browser
CPE 401/601 Lecture 4 : I/O Multiplexing
9
Example - generic TCP client
TCP SOCKET
• Input from standard input should be sent to a
TCP socket
• Input from a TCP socket should be sent to
standard output
• How do we know when to check for input
from each source?
CPE 401/601 Lecture 4 : I/O Multiplexing
STDIN
STDOUT
10
Options
• Use multiple processes/threads
• Use nonblocking I/O
– use fcntl() to set O_NONBLOCK
• Use alarm and signal handler to interrupt slow
system calls
• Use functions that support checking of
multiple input sources at the same time
CPE 401/601 Lecture 4 : I/O Multiplexing
11
Non blocking I/O
• Tell kernel not to block a process if I/O
requests can not be completed
• use fcntl() to set O_NONBLOCK:
int flags;
flags = fcntl(sock,F_GETFL,0);
fcntl(sock,F_SETFL,flags |
O_NONBLOCK);
• Now calls to read() (and other system calls)
will return an error and set errno to
EWOULDBLOCK
CPE 401/601 Lecture 4 : I/O Multiplexing
12
Non blocking I/O
while (! done) {
if ( (n=read(STDIN_FILENO,…)<0))
if (errno != EWOULDBLOCK)
/* ERROR */
else write(tcpsock,…)
if ( (n=read(tcpsock,…)<0))
if (errno != EWOULDBLOCK)
/* ERROR */
else write(STDOUT_FILENO,…)
}
CPE 401/601 Lecture 4 : I/O Multiplexing
13
The problem with nonblocking I/O
• Using blocking I/O allows the OS to put your
process to sleep when nothing is happening
– Once input arrives, the OS will wake up your
process and read() (or whatever) will return
• With nonblocking I/O, the process will chew
up all available processor time!!!
CPE 401/601 Lecture 4 : I/O Multiplexing
14
Using alarms
signal(SIGALRM, sig_alrm);
alarm(MAX_TIME);
read(STDIN_FILENO,…);
...
A function you write
signal(SIGALRM, sig_alrm);
alarm(MAX_TIME);
read(tcpsock,…);
...
CPE 401/601 Lecture 4 : I/O Multiplexing
15
“Alarming” Issues
• What will happen to the response time ?
• What is the ‘right’ value for MAX_TIME?
CPE 401/601 Lecture 4 : I/O Multiplexing
16
Select()
• The select() system call allows us to use
blocking I/O on a set of descriptors
– file, socket, …
• We can ask select to notify us when data is
available for reading on either STDIN or a
socket
CPE 401/601 Lecture 4 : I/O Multiplexing
17
select()
int select( int maxfd,
fd_set *readset,
fd_set *writeset,
fd_set *excepset,
const struct timeval *timeout);
•
•
•
•
•
maxfd:
readset:
writeset:
excepset:
timeout:
highest number assigned to a descriptor
set of descriptors we want to read from
set of descriptors we want to write to
set of descriptors to watch for exceptions
maximum time select should wait
CPE 401/601 Lecture 4 : I/O Multiplexing
18
struct timeval
struct timeval {
long tv_sec;
/* seconds */
long tv_usec;
/* microseconds */
}
struct timeval max = {1,0};
• To return immediately after checking
descriptors
– set timeout as {0, 0}
• To wait until I/O is ready
– set timeout as a NULL pointer
CPE 401/601 Lecture 4 : I/O Multiplexing
19
fd_set
• Operations you can use with an fd_set:
– Clear all bits in fd_set
void FD_ZERO(fd_set *fdset);
– Turn on the bit for fd in fd_set
void FD_SET(int fd, fd_set *fdset);
– Turn off the bit for fd in fd_set
void FD_CLR(int fd, fd_set *fdset);
– Check whether the bit for fd in fd_set is on
int FD_ISSET(int fd, fd_set *fdset);
CPE 401/601 Lecture 4 : I/O Multiplexing
20
Using select()
• Create fd_set
• Clear the whole thing with FD_ZERO
• Add each descriptor you want to watch using
FD_SET
• Call select
• when select returns, use FD_ISSET to see if I/O
is possible on each descriptor
CPE 401/601 Lecture 4 : I/O Multiplexing
21
Client/Server Programming
Issues in Client/Server Programming
• Identifying the Server
• Looking up an IP address
• Looking up a well known port name
• Specifying a local IP address
• UDP/TCP client design
CPE 401/601 Lecture 4 : Client/Server Issues
23
Identifying the Server
• Options:
– hard-coded into the client program
– require that the user identify the server
– read from a configuration file
– use a separate protocol/network service to lookup
the identity of the server.
CPE 401/601 Lecture 4 : Client/Server Issues
24
Identifying a TCP/IP server
• Need an IP address, protocol and port
– We often use host names instead of IP addresses
– usually the protocol is not specified by the user
• UDP vs. TCP
– often the port is not specified by the user
CPE 401/601 Lecture 4 : Client/Server Issues
25
Services and Ports
• Many services are available via “well known”
addresses (names)
• There is a mapping of service names to port
numbers:
struct *servent getservbyname(
char *service, char *protocol );
• servent->s_port is the port number in network
byte order
CPE 401/601 Lecture 4 : Client/Server Issues
26
Specifying a Local Address
• When a client creates and binds a socket,
it must specify a local port and IP address
• Typically clients don’t care what port it is on:
haddr->port = htons(0);
give me any available port !
CPE 401/601 Lecture 4 : Client/Server Issues
27
Local IP address
• A client can also ask the operating system to
take care of specifying the local IP address:
haddr->sin_addr.s_addr=
htonl(INADDR_ANY);
Give me the appropriate address
CPE 401/601 Lecture 4 : Client/Server Issues
28
UDP Client Design
• Establish server address (IP and port)
• Allocate a socket
• Specify that any valid local port and IP
address can be used
• Communicate with server (send, recv)
• Close the socket
CPE 401/601 Lecture 4 : Client/Server Issues
29
Connected mode UDP
• A UDP client can call connect() to establish the
address of the server
• The UDP client can then use read() and write()
or send() and recv()
• A UDP client using a connected mode socket
can only talk to one server
– using the connected-mode socket
CPE 401/601 Lecture 4 : Client/Server Issues
30
TCP Client Design
• Establish server address (IP and port)
• Allocate a socket
• Specify that any valid local port and IP
address can be used
• Call connect()
• Communicate with server (read, write)
• Close the connection
CPE 401/601 Lecture 4 : Client/Server Issues
31
Closing a TCP socket
• Many TCP based application protocols support
– multiple requests and/or
– variable length requests over a single TCP
connection
• How does the server known when the client
is done ?
– and it is OK to close the socket ?
CPE 401/601 Lecture 4 : Client/Server Issues
32
Partial Close
• One solution is for the client to shut down
only it’s writing end of the socket
• shutdown() system call provides this function
shutdown(int s, int direction);
– direction can be 0 to close the reading end or 1 to
close the writing end
– shutdown sends info to the other process!
CPE 401/601 Lecture 4 : Client/Server Issues
33
TCP sockets programming
• Common problem areas:
– null termination of strings
– reads don’t correspond to writes
– synchronization (including close())
– ambiguous protocol
CPE 401/601 Lecture 4 : Client/Server Issues
34
TCP Reads
• Each call to read() on a TCP socket returns any
available data
– up to a maximum
• TCP buffers data at both ends of the
connection
• You must be prepared to accept data 1 byte at
a time from a TCP socket!
CPE 401/601 Lecture 4 : Client/Server Issues
35
Server Design
Concurrent
Large or variable size requests
Harder to program
Typically uses more system resources
Iterative
Small, fixed size requests
Easy to program
CPE 401/601 Lecture 4 : Client/Server Issues
36
Server Design
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
CPE 401/601 Lecture 4 : Client/Server Issues
37
Server Design
Iterative
Connectionless
Iterative
Connection-Oriented
Concurrent
Connectionless
Concurrent
Connection-Oriented
CPE 401/601 Lecture 4 : Client/Server Issues
38
Statelessness
• State: Information that a server maintains
about the status of ongoing client interactions
• Connectionless servers that keep state
information must be designed carefully!
Messages can be duplicated!
CPE 401/601 Lecture 4 : Client/Server Issues
39
The Dangers of Statefullness
• Clients can go down at any time
• Client hosts can reboot many times
• The network can lose messages
• The network can duplicate messages
CPE 401/601 Lecture 4 : Client/Server Issues
40
Concurrent Server Design Alternatives
• One child per client
• Spawn one thread per client
• Preforking multiple processes
• Prethreaded Server
CPE 401/601 Lecture 4 : Client/Server Issues
41
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()
CPE 401/601 Lecture 4 : Client/Server Issues
42
One thread per client
• Almost like using fork
– call pthread_create instead
• Using threads makes it easier to have sibling
processes share information
– less overhead
• Sharing information must be done carefully
– use pthread_mutex
CPE 401/601 Lecture 4 : Client/Server Issues
43
Prefork()’d Server
• Creating a new process for each client is
expensive
• We can create a bunch of processes, each of
which can take care of a client
• Each child process is an iterative server
CPE 401/601 Lecture 4 : Client/Server Issues
44
Prefork()’d TCP Server
• Initial process creates socket and binds to well
known address.
• Process now calls fork() a bunch of times
• All children call accept()
• The next incoming connection will be handed
to one child
CPE 401/601 Lecture 4 : Client/Server Issues
45
Preforking
• Having too many preforked children can be
bad
• Using dynamic process allocation instead of a
hard-coded number of children can avoid
problems
• Parent process just manages the children
– doesn’t worry about clients
CPE 401/601 Lecture 4 : Client/Server Issues
46
Sockets library vs. system call
• A preforked TCP server won’t always work
if sockets is not part of the kernel
– calling accept() is a library call, not an atomic
operation
• We can get around this by making sure only
one child calls accept() at a time using some
locking scheme
CPE 401/601 Lecture 4 : Client/Server Issues
47
Prethreaded Server
• Same benefits as preforking
• Can also have the main thread do all the calls
to accept()
– and hand off each client to an existing thread
CPE 401/601 Lecture 4 : Client/Server Issues
48
What’s the best server design?
• Many factors:
– expected number of simultaneous clients
– Transaction size
• time to compute or lookup the answer
– Variability in transaction size
– Available system resources
• perhaps what resources can be required in order to run
the service
CPE 401/601 Lecture 4 : Client/Server Issues
49
Server Design
• It is important to understand the issues and
options
• Knowledge of queuing theory can be a big
help
• You might need to test a few alternatives to
determine the best design
CPE 401/601 Lecture 4 : Client/Server Issues
50