Top Banner
Lecture 11 Overview
48

Lecture 11 Overview

Mar 19, 2016

Download

Documents

livana

Lecture 11 Overview. Creating a TCP socket. int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen); int mysock; struct sockaddr_in myaddr; mysock = socket(PF_INET,SOCK_STREAM,0); myaddr.sin_family = AF_INET; myaddr.sin_port = htons( 80 ); - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Lecture 11 Overview

Lecture 11 Overview

Page 2: Lecture 11 Overview

Creating a TCP socketint bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);

int mysock;struct sockaddr_in myaddr;mysock = socket(PF_INET,SOCK_STREAM,0);myaddr.sin_family = AF_INET;myaddr.sin_port = htons( 80 );myaddr.sin_addr = htonl( INADDR_ANY );bind(mysock, (sockaddr *) &myaddr, sizeof(myaddr));

2CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 3: Lecture 11 Overview

Establishing a passive mode TCP socket

• Passive mode:– Address already determined

• Tell the kernel to accept incoming connection requests directed at the socket address– 3-way handshake

• Tell the kernel to queue incoming connections for us

3CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 4: Lecture 11 Overview

listen()int listen(int sockfd, int backlog);

• sockfd is the TCP socket – already bound to an address

• backlog is the number of incoming connections the kernel should be able to keep track of (queue for us)– Sum of incomplete and completed queues

4CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 5: Lecture 11 Overview

Accepting an incoming connection

• Once we call listen(), the O.S. will queue incoming connections– Handles the 3-way handshake– Queues up multiple connections

• When our application is ready to handle a new connection– we need to ask the O.S. for the next connection

5CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 6: Lecture 11 Overview

accept()int accept( int sockfd, struct sockaddr* cliaddr, socklen_t *addrlen);

• sockfd is the passive mode TCP socket– initiated by socket(), bind(), and listen()

• cliaddr is a pointer to allocated space• addrlen is a value-result argument– must be set to the size of cliaddr– on return, will be set to be the number of used bytes in

cliaddr

6CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 7: Lecture 11 Overview

Terminating a TCP connectionint close(int sockfd);

• Either end of the connection can call the close() system call

• What if there is data being sent?

• If the other end has closed the connection, and there is no buffered data, reading from a TCP socket returns 0 to indicate EOF.

7CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 8: Lecture 11 Overview

Client Code• TCP clients can call connect() which:– takes care of establishing an endpoint address for

the client socket– Attempts to establish a connection to the

specified server• 3-way handshake

• no need to call bind first, the O.S. will take care of assigning the local endpoint address – TCP port number, IP address

8CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 9: Lecture 11 Overview

connect()int connect( int sockfd, const struct sockaddr *server, socklen_t addrlen);

• sockfd is an already created TCP socket• server contains the address of the server • connect() returns 0 if OK, -1 on error– No response to SYN segment (3 trials)– RST signal– ICMP destination unreachable (3 trials)

9CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 10: Lecture 11 Overview

Reading from a TCP socketint read(int fd, char *buf, int max);

• By default read() will block until data is available

• reading from a TCP socket may return less than max bytes– whatever is available

• You must be prepared to read data 1 byte at a time!

10CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 11: Lecture 11 Overview

Writing to a TCP socketint write(int fd, char *buf, int num);

• write might not be able to write all num bytes on a nonblocking socket

• readn(), writen() and readline() functions

11CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 12: Lecture 11 Overview

Creating a UDP socketint 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));

12CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 13: Lecture 11 Overview

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 destination address• Return value is the number of bytes sent, – or -1 on error.

13CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 14: Lecture 11 Overview

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!!!

• You can send 0 bytes of data!14CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 15: Lecture 11 Overview

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

15CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 16: Lecture 11 Overview

recvfrom()• If buff is not large enough, any extra data is

lost forever...• You can receive 0 bytes of data!• recvfrom doesn’t return until there is a

datagram available,• You should set fromaddrlen before calling• If from and fromaddrlen are NULL we don’t

find out who sent the data

16CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 17: Lecture 11 Overview

Typical UDP Communication

17CPE 401/601 Lecture 11 : TCP & UDP Socket Programming

Page 18: Lecture 11 Overview

Lecture 12

Socket Programming Issues

CPE 401 / 601

Computer Network Systems

slides are modified from Dave Hollingerslides are modified from Dave Hollinger

Page 19: Lecture 11 Overview

Debugging• Debugging can be difficult

• Write routines to print out sockaddrs

• Use trace, strace, ptrace, truss, etc

• Include code that can handle unexpected situations

19CPE 401/601 Lecture 12 : Socket Programming Issues

Page 20: Lecture 11 Overview

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

20CPE 401/601 Lecture 12 : Socket Programming Issues

There are some other (better) ways to do this

Page 21: Lecture 11 Overview

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

21CPE 401/601 Lecture 12 : Socket Programming Issues

Page 22: Lecture 11 Overview

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

22

OS Specific, some won’t do this!

CPE 401/601 Lecture 12 : Socket Programming Issues

Page 23: Lecture 11 Overview

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

23CPE 401/601 Lecture 12 : Socket Programming Issues

Page 24: Lecture 11 Overview

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)

24CPE 401/601 Lecture 12 : Socket Programming Issues

Page 25: Lecture 11 Overview

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

25CPE 401/601 Lecture 12 : I/O Multiplexing

Page 26: Lecture 11 Overview

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?

26

STDIN

STDOUT

TCP

SOC

KET

CPE 401/601 Lecture 12 : I/O Multiplexing

Page 27: Lecture 11 Overview

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

27CPE 401/601 Lecture 12 : I/O Multiplexing

Page 28: Lecture 11 Overview

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

28CPE 401/601 Lecture 12 : I/O Multiplexing

Page 29: Lecture 11 Overview

Non blocking I/Owhile (! 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,…)}

29CPE 401/601 Lecture 12 : I/O Multiplexing

Page 30: Lecture 11 Overview

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!!!

30CPE 401/601 Lecture 12 : I/O Multiplexing

Page 31: Lecture 11 Overview

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

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

31

A function you write

CPE 401/601 Lecture 12 : I/O Multiplexing

Page 32: Lecture 11 Overview

“Alarming” Issues• What will happen to the response time ?

• What is the ‘right’ value for MAX_TIME?

32CPE 401/601 Lecture 12 : I/O Multiplexing

Page 33: Lecture 11 Overview

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

33CPE 401/601 Lecture 12 : I/O Multiplexing

Page 34: Lecture 11 Overview

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

34CPE 401/601 Lecture 12 : I/O Multiplexing

Page 35: Lecture 11 Overview

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

35CPE 401/601 Lecture 12 : I/O Multiplexing

Page 36: Lecture 11 Overview

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

36CPE 401/601 Lecture 12 : I/O Multiplexing

Page 37: Lecture 11 Overview

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

37CPE 401/601 Lecture 12 : I/O Multiplexing

Page 38: Lecture 11 Overview

Error HandlingIssues and Ideas

Page 39: Lecture 11 Overview

System Calls and Errors• In general, systems calls return a negative

number to indicate an error– We often want to find out what error– Servers generally add this information to a log– Clients generally provide some information to the

user

39CPE 401/601 Lecture 12 : Error Handling

Page 40: Lecture 11 Overview

extern int errno;• Whenever an error occurs, system calls set the

value of the global variable errno– You can check errno for specific errors

• 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• printf makes a call to write!

40CPE 401/601 Lecture 12 : Error Handling

Page 41: Lecture 11 Overview

Error codes• Error codes are defined in errno.hEAGAIN EBADF EACCESSEBUSY EINTR EINVALEIO ENODEV EPIPE …• Support routines• void perror(const char *string);– stdio.h

• char *strerror(int errnum);– string.h

41CPE 401/601 Lecture 12 : Error Handling

Page 42: Lecture 11 Overview

General Strategies • Include code to check for errors after every

system call

• Develop "wrapper functions" that do the checking for you

• Develop layers of functions, each hides some of the error-handling details

42CPE 401/601 Lecture 12 : Error Handling

Page 43: Lecture 11 Overview

Example wrapperint Socket( int f, int t, int p) {int n;if ( (n=socket(f,t,p)) < 0 ) ) {

perror("Fatal Error");exit(1);

}return(n);

}

43CPE 401/601 Lecture 12 : Error Handling

Page 44: Lecture 11 Overview

What is fatal?• How do you know what should be a fatal

error?– Common sense– If the program can continue – it should

– if a server can't create a socket, or can't bind to it's port• there is no sense continuing…

44CPE 401/601 Lecture 12 : Error Handling

Page 45: Lecture 11 Overview

Wrappers are great!• Wrappers like those used in the text can make

code much more readable

• There are always situations in which you cannot use the wrappers– Sometimes system calls are "interrupted" (EINTR) • this is not always a fatal error !

45CPE 401/601 Lecture 12 : Error Handling

Page 46: Lecture 11 Overview

Another approach• Instead of simple wrapper functions, you

might develop a layered system

• The idea is to "hide" the sockaddr and error handling details behind a few custom functions:– int tcp_client(char *server, int port);– int tcp_server(int port);

46CPE 401/601 Lecture 12 : Error Handling

Page 47: Lecture 11 Overview

Layers and Code Re-use• Developing general functions that might be

re-used in other programs is obviously "a good thing"

• Layering is beneficial even if the code is not intended to be re-used:– hide error-handling from "high-level" code– hide other details– often makes debugging easier

47CPE 401/601 Lecture 12 : Error Handling

Page 48: Lecture 11 Overview

The Best Approach to handling errors

• There is no best approach• Do what works for you

• Make sure you check all system calls for errors!– Not checking can lead to security problems!– Not checking can lead to bad grades on

assignments!

48CPE 401/601 Lecture 12 : Error Handling