Lecture 8 UDP Sockets & I/O Multiplexing

38
Lecture 8 UDP Sockets & I/O Multiplexing CPE 401 / 601 Computer Network Systems slides are modified from Dave Hollinger

description

Lecture 8 UDP Sockets & I/O Multiplexing. CPE 401 / 601 Computer Network Systems. slides are modified from Dave Hollinger. Lab 1 demo schedule Lab 1/2 Questions ???. “no frills,” “bare bones” Internet transport protocol “best effort” service, UDP segments may be: lost - PowerPoint PPT Presentation

Transcript of Lecture 8 UDP Sockets & I/O Multiplexing

Page 1: Lecture 8 UDP Sockets & I/O Multiplexing

Lecture 8

UDP Sockets &I/O Multiplexing

CPE 401 / 601Computer Network Systems

slides are modified from Dave Hollinger

Page 2: Lecture 8 UDP Sockets & I/O Multiplexing

Lab 1 demo schedule

Lab 1/2 Questions ???

2

Page 3: Lecture 8 UDP Sockets & I/O Multiplexing

UDP: User Datagram Protocol [RFC 768]

“no frills,” “bare bones” Internet transport protocol

“best effort” service, UDP segments may be: lost delivered out of order to

app

connectionless: no handshaking

between UDP sender, receiver

each UDP segment handled independently of others

Why is there a UDP? no connection

establishment (which can add delay)

simple: no connection state at sender, receiver

small segment header no congestion control: UDP

can blast away as fast as desired

UDP Sockets 3

Page 4: Lecture 8 UDP Sockets & I/O Multiplexing

UDP: more often used for streaming

multimedia apps loss tolerant rate sensitive

other UDP uses DNS SNMP

reliable transfer over UDP: add reliability at application layer application-specific

error recovery!

source port # dest port #

32 bits

Applicationdata (message)

UDP segment format

length checksumLength of UDP

segment includingheader, in bytes,

UDP Sockets 4

Page 5: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 5

UDP Sockets Programming Creating UDP sockets.

Client Server

Sending data.

Receiving data.

Connected Mode.

Page 6: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 6

Creating a UDP socket

int socket(int family, int type, int proto);

int sock;sock = socket(PF_INET, SOCK_DGRAM,0);

if (sock<0) { /* ERROR */ }

Page 7: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 7

Binding to well known address(typically done by server only)int mysock;struct sockaddr_in myaddr;

mysock = socket(PF_INET,SOCK_DGRAM,0);myaddr.sin_family = AF_INET;myaddr.sin_port = htons( 1234 );myaddr.sin_addr = htonl( INADDR_ANY );

bind(mysock, &myaddr, sizeof(myaddr));

Page 8: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 8

Sending UDP Datagramsssize_t sendto( int sockfd,

void *buff,size_t nbytes,int flags,

const struct sockaddr* to, socklen_t addrlen);

sockfd is a UDP socket buff is the address of the data (nbytes long) to is the address of a sockaddr containing the

destination address. Return value is the number of bytes sent, or -1

on error.

Page 9: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 9

sendto()

You can send 0 bytes of data!

Some possible errors :EBADF, ENOTSOCK: bad socket descriptorEFAULT: bad buffer addressEMSGSIZE: message too largeENOBUFS: system buffers are full

Page 10: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 10

More sendto() The return value of sendto() indicates

how much data was accepted by the O.S. for sending as a datagram not how much data made it to the destination.

There is no error condition that indicates that the destination did not get the data!!!

Page 11: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 11

Receiving UDP Datagramsssize_t recvfrom( int sockfd, void *buff, size_t nbytes, int flags, struct sockaddr* from, socklen_t *fromaddrlen);

sockfd is a UDP socket buff is the address of a buffer (nbytes long) from is the address of a sockaddr. Return value is the number of bytes received

and put into buff, or -1 on error.

Page 12: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 12

recvfrom()

If buff is not large enough, any extra data is lost forever...

You can receive 0 bytes of data!

Same errors as sendto, but also: EINTR: System call interrupted by signal.

Page 13: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 13

More recvfrom() recvfrom doesn’t return until there is a

datagram available, unless you do something special

The sockaddr at from is filled in with the address of the sender.

You should set fromaddrlen before calling.

If from and fromaddrlen are NULL we don’t find out who sent the data.

Page 14: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 14

Typical UDP client code Create UDP socket.

Create sockaddr with address of server.

Call sendto(), sending request to the server. No call to bind() is necessary!

Possibly call recvfrom() (if we need a reply).

Page 15: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 15

Typical UDP Server code Create UDP socket and bind to well

known address.

Call recvfrom() to get a request, noting the address of the client.

Process request and send reply back with sendto().

Page 16: Lecture 8 UDP Sockets & I/O Multiplexing

UDP sockets 16

Page 17: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 17

UDP Echo Serverint mysock;struct sockaddr_in myaddr, cliaddr;char msgbuf[MAXLEN];socklen_t clilen;int msglen;

mysock = socket(PF_INET,SOCK_DGRAM,0);myaddr.sin_family = AF_INET;myaddr.sin_port = htons( S_PORT );myaddr.sin_addr = htonl( INADDR_ANY );

bind(mysock, &myaddr, sizeof(myaddr));while (1) {

len=sizeof(cliaddr);msglen=recvfrom(mysock,msgbuf,MAXLEN,0,cliaddr,&clilen);sendto(mysock,msgbuf,msglen,0,cliaddr,clilen);

}

NEED TO CHECK

FOR ERRORS!!!

Page 18: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 18

Debugging Debugging UDP can be difficult.

Write routines to print out sockaddrs.

Use trace, strace, ptrace, truss, etc.

Include code that can handle unexpected situations.

Page 19: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 19

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()

Page 20: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 20

recvfrom()and alarm()signal(SIGALRM, sig_alrm);alarm(max_time_to_wait);if (recvfrom(…)<0)

if (errno==EINTR)/* timed out */

else/* some other error */

else/* no error or time out - turn off alarm */alarm(0);There are some other (better) ways to do

this - check out section 13.2

Page 21: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 21

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.

Page 22: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 22

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!

Page 23: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 23

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.

Page 24: Lecture 8 UDP Sockets & I/O Multiplexing

UDP Sockets 24

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).

Page 25: Lecture 8 UDP Sockets & I/O Multiplexing
Page 26: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 26

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

Page 27: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 27

Example - generic TCP client 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?

STDIN

STDOUT

TCP

SOC

KET

Page 28: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 28

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.

Page 29: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 29

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.

Page 30: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 30

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,…)}

Page 31: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 31

The problem with nonblocking I/O

Using blocking I/O allows the OS to put your process to sleep when nothing is happening (no input). 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!!!

Page 32: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 32

Using alarms

signal(SIGALRM, sig_alrm);alarm(MAX_TIME);read(STDIN_FILENO,…);...

signal(SIGALRM, sig_alrm);alarm(MAX_TIME);read(tcpsock,…);...

A function you write

Page 33: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 33

Alarming Problem

What will happen to the response time ?

What is the ‘right’ value for MAX_TIME?

Page 34: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 34

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.

Page 35: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 35

select()int select( int maxfd,

fd_set *readset, fd_set *writeset, fd_set *excepset, const struct timeval *timeout);

maxfd: highest number assigned to a descriptor.readset: set of descriptors we want to read from.writeset: set of descriptors we want to write to.excepset: set of descriptors to watch for exceptions.timeout: maximum time select should wait

Page 36: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 36

struct timevalstruct 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.

Page 37: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 37

fd_set Operations you can use with an fd_set:

Clear all bits in fd_setvoid FD_ZERO( fd_set *fdset); Turn on the bit for fd in fd_setvoid FD_SET( int fd, fd_set *fdset); Turn off the bit for fd in fd_setvoid FD_CLR( int fd, fd_set *fdset); Check whether the bit for fd in fd_set is onint FD_ISSET( int fd, fd_set *fdset);

Page 38: Lecture 8 UDP Sockets & I/O Multiplexing

Multiplexing 38

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.