Download TCP/UDP Sockets

Document related concepts

Flow-based programming wikipedia , lookup

Logic programming wikipedia , lookup

Programming language wikipedia , lookup

Falcon (programming language) wikipedia , lookup

Subroutine wikipedia , lookup

C syntax wikipedia , lookup

Stream processing wikipedia , lookup

Abstraction (computer science) wikipedia , lookup

Functional programming wikipedia , lookup

Object-oriented programming wikipedia , lookup

Go (programming language) wikipedia , lookup

IBM TPNS wikipedia , lookup

C Sharp (programming language) wikipedia , lookup

Reactive programming wikipedia , lookup

Structured programming wikipedia , lookup

Transcript
Lecture 15 Overview
Network API
• Application Programming Interface
– Services that provide the interface between
application and protocol software
• often by the operating system
Application
Network API
Protocol A
CPE 401/601 Lecture 15 : Socket Programming
Protocol B
Protocol C
2
Network API wish list
• Generic Programming Interface
– Support multiple communication protocol suites
(families)
– Address (endpoint) representation independence
– Provide special services for Client and Server?
• Support for message oriented and connection
oriented communication
• Work with existing I/O services
– when this makes sense
• Operating System independence
CPE 401/601 Lecture 15 : Socket Programming
3
Socket
• A socket is an abstract representation of a
communication endpoint
• Sockets work with Unix I/O services just like
files, pipes & FIFOs
• Sockets needs to
– establishing a connection
– specifying communication endpoint addresses
CPE 401/601 Lecture 15 : Socket Programming
4
Creating a Socket
int socket(int family, int type,
int proto);
• family specifies the protocol family
– PF_INET for TCP/IP
• type specifies the type of service
– SOCK_STREAM, SOCK_DGRAM
• protocol specifies the specific protocol
– usually 0, which means the default
CPE 401/601 Lecture 15 : Socket Programming
5
socket()
• The socket() system call returns a socket
descriptor (small integer) or -1 on error
• socket() allocates resources needed for a
communication endpoint
– but it does not deal with endpoint addressing
CPE 401/601 Lecture 15 : Socket Programming
6
Specifying an Endpoint Address
• Sockets API is generic
• There must be a generic way to specify
endpoint addresses
• TCP/IP requires an IP address and a port
number for each endpoint address
• Other protocol suites (families) may use other
schemes
CPE 401/601 Lecture 15 : Socket Programming
7
sockaddr
sockaddr_in6
length
AF_INET6
port
sockaddr
sa_len
sa_family
sockaddr_in
length
AF_INET
port
addr
Flow-label
sa_data
addr
zero
Scope ID
variable
16 bytes
28 bytes
CPE 401/601 Lecture 15 : Socket Programming
8
struct sockaddr_in (IPv4)
Length of
struct sockaddr_in {
structure (16)
uint8_t
sin_len;
AF_INET
sa_family_t
sin_family;
in_port_t
sin_port;
16 bit
Port number
struct in_addr sin_addr;
char
sin_zero[8];
Make structure
};
16 bytes
struct in_addr {
in_addr_t
s_addr;
32 bit
IPv4 address
};
CPE 401/601 Lecture 15 : Socket Programming
9
struct sockaddr_in (IPv6)
struct sockaddr_in6 {
Length of
structure (28)
uint8_t
sin6_len;
AF_INET6
sa_family_t
sin6_family;
in_port_t
sin6_port;
Port number
uint32_t
sin6_flowinfo;
Flow label
struct in6_addr sin6_addr;
Scope of
uint32_t
sin6_scope_id;
address
};
struct in6_addr {
128 bit
uint8_t
s6_addr[16];
IPv6 address
10
CPE 401/601 Lecture 15 : Socket Programming
};
Network Byte Order
• All values stored in a sockaddr_in must be in
network byte order.
– sin_port a TCP/IP port number
– sin_addr an IP address
•
•
•
•
uint16_t
uint16_t
uint32_t
uint32_t
htons(uint16_t);
ntohs(uint_16_t);
htonl(uint32_t);
ntohl(uint32_t);
CPE 401/601 Lecture 15 : Socket Programming
11
TCP/IP Addresses
• We don’t need to deal with sockaddr
structures since we will only deal with a real
protocol family.
• We can use sockaddr_in structures
• BUT: The C functions that make up the sockets
API expect structures of type sockaddr
CPE 401/601 Lecture 15 : Socket Programming
12
Assigning an address to a socket
• The bind() system call is used to assign an
address to an existing socket.
int bind( int sockfd,
const struct sockaddr *myaddr,
int addrlen);
• You can give bind() a sockaddr_in structure:
int bind( mysock,
(struct sockaddr*) &myaddr,
sizeof(myaddr) );
CPE 401/601 Lecture 15 : Socket Programming
13
bind() Example
int mysock,err;
struct sockaddr_in myaddr;
mysock =
socket(PF_INET,SOCK_STREAM,0);
myaddr.sin_family = AF_INET;
myaddr.sin_port = htons( portnum );
myaddr.sin_addr = htonl( ipaddress);
err=bind(mysock, (sockaddr *)
&myaddr, sizeof(myaddr));
CPE 401/601 Lecture 15 : Socket Programming
14
Port schmort - who cares ?
• Clients typically don’t care what port they are
assigned
• When you call bind you can tell it to assign
you any available port:
– myaddr.port = htons(0);
CPE 401/601 Lecture 15 : Socket Programming
15
What is my IP address ?
• How can you find out what your IP address is
so you can tell bind() ?
• There is no realistic way for you to know the
right IP address to give bind()
– what if the computer has multiple network
interfaces?
• specify the IP address as: INADDR_ANY, this
tells the OS to take care of things.
CPE 401/601 Lecture 15 : Socket Programming
16
IPv4 Address Conversion
int inet_aton(char *, struct in_addr *);
– Convert ASCII dotted-decimal IP address to
network byte ordered 32 bit value.
– Returns 1 on success, 0 on failure.
char *inet_ntoa(struct in_addr);
– Convert network byte ordered value to ASCII
dotted-decimal (a string).
CPE 401/601 Lecture 15 : Socket Programming
17
IPv4 & IPv6 Address Conversion
int inet_pton(int, const char*, void*);
– (family, string_ptr, address_ptr)
– Convert IP address string to network byte ordered
32 or 128 bit value
– 1 on success, -1 on failure, 0 on invalid input
char *inet_ntop(int, const void*, char*,
size_t);
– (family, address_ptr, string_ptr, length)
– Convert network byte ordered value to IP address
string
• x:x:x:x:x:x:x:x or x:x:x:x:x:x:a.b.c.d
CPE 401/601 Lecture 15 : Socket Programming
18
Other socket system calls
• General Use
– read()
– write()
– close()
• Connection-oriented (TCP)
– connect()
– listen()
– accept()
• Connectionless (UDP)
– send()
– recv()
CPE 401/601 Lecture 15 : Socket Programming
19
Lecture 16
TCP and UDP Sockets
CPE 401 / 601
Computer Network Systems
slides
modified
from
Dave
Hollinger
slides
are are
modified
from
Dave
Hollinger
TCP Sockets Programming
• Creating a passive mode (server) socket
• Establishing an application-level connection
• send/receive data
• Terminating a connection
CPE 401/601 Lecture 16 : TCP Socket Programming
21
TCP state diagram
Creating a TCP socket
int socket(int family,int type,int proto);
– family: AF_INET, AF_INET6, AF_LOCAL, …
– type: SOCK_STREAM, SOCK_DGRAM,
SOCK_SEQPACKET, SOCK_RAW
– protocol: IPPROTO_TCP, IPPROTO_UDP,
IPPROTO_SCTP
int sock;
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock<0) { /* ERROR */ }
CPE 401/601 Lecture 16 : TCP Socket Programming
23
Binding to well known address
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 );
myaddr.sin_addr = htonl( INADDR_ANY );
bind(mysock, (sockaddr *) &myaddr,
sizeof(myaddr));
CPE 401/601 Lecture 16 : TCP Socket Programming
24
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
CPE 401/601 Lecture 16 : TCP Socket Programming
25
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
CPE 401/601 Lecture 16 : TCP Socket Programming
26
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
CPE 401/601 Lecture 16 : TCP Socket Programming
27
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
CPE 401/601 Lecture 16 : TCP Socket Programming
28
accept() return value
• accept() returns a new socket descriptor
(small positive integer) or -1 on error
• After accept returns a new socket descriptor,
I/O can be done using the read() and write()
system calls
• read() and write() operate a little differently
on sockets!
– vs. file operation!
CPE 401/601 Lecture 16 : TCP Socket Programming
29
Terminating a TCP connection
int 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.
CPE 401/601 Lecture 16 : TCP Socket Programming
30
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
CPE 401/601 Lecture 16 : TCP Socket Programming
31
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)
CPE 401/601 Lecture 16 : TCP Socket Programming
32
Reading from a TCP socket
int 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!
CPE 401/601 Lecture 16 : TCP Socket Programming
33
Writing to a TCP socket
int 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
CPE 401/601 Lecture 16 : TCP Socket Programming
34
Metaphor for Good Relationships
• To succeed in relationships*:
– you need to establish your own identity.
– you need to be open & accepting.
– you need to establish contacts.
– you need to take things as they come, not as you
expect them.
– you need to handle problems as they arise.
*Copyright Dr. Laura’s Network Programming Corp.
CPE 401/601 Lecture 16 : TCP Socket Programming
35
UDP Sockets
UDP Sockets Programming
• Creating UDP sockets
– Client
– Server
• Sending data
• Receiving data
• Connected Mode
CPE 401/601 Lecture 16 : UDP Socket Programming
37
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 */ }
CPE 401/601 Lecture 16 : UDP Socket Programming
38
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));
CPE 401/601 Lecture 16 : UDP Socket Programming
39
Sending UDP Datagrams
ssize_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.
CPE 401/601 Lecture 16 : UDP Socket Programming
40
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!
CPE 401/601 Lecture 16 : UDP Socket Programming
41
Receiving UDP Datagrams
ssize_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
CPE 401/601 Lecture 16 : UDP Socket Programming
42
recvfrom()
• If buff is not large enough, any extra data is
lost forever...
• You can receive 0 bytes of data!
• The sockaddr at from is filled in with the
address of the sender
CPE 401/601 Lecture 16 : UDP Socket Programming
43
More recvfrom()
• recvfrom doesn’t return until there is a
datagram available,
– unless you do something special
• You should set fromaddrlen before calling
• If from and fromaddrlen are NULL we don’t
find out who sent the data
CPE 401/601 Lecture 16 : UDP Socket Programming
44
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
CPE 401/601 Lecture 16 : UDP Socket Programming
45
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()
CPE 401/601 Lecture 16 : UDP Socket Programming
46
Typical UDP Communication
CPE 401/601 Lecture 16 : UDP Socket Programming
47
UDP Echo Server
int 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) {
clilen=sizeof(cliaddr);
msglen=recvfrom(mysock,msgbuf,MAXLEN,0,
cliaddr,&clilen);
sendto(mysock,msgbuf,msglen,0,cliaddr,clilen);
}
CPE 401/601 Lecture 16 : UDP Socket Programming
48
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
CPE 401/601 Lecture 16 : UDP Socket Programming
49
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()
CPE 401/601 Lecture 16 : UDP Socket Programming
50
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 */
There are some other
alarm(0);
(better) ways to do this
CPE 401/601 Lecture 16 : UDP Socket Programming
51
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 16 : UDP Socket Programming
52
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 16 : UDP Socket Programming
53
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 16 : UDP Socket Programming
54
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 16 : UDP Socket Programming
55