TCP/IP Application Interface
Loosely specified for TCP/IP
UC-Berkeley:
UNIX sockets Microsoft: Windows Sockets AT&T System V: TLI
Subset of system calls
Existing UNIX File IOs
Basic file IO operations
open
-- prepare a device or file for IO close -- terminate use of opened device or file read -- obtain data from from an open file or device write -- store data into an open file or device seek -- move to a specific position in a file or device ioctl -- control or configure a device
Is UNIX File IO Good Enough?
It provides a basic model of IO access
Not sufficient! network addresses client vs. server different transport layers
Socket Descriptors
Treat as traditional file descriptors File descriptor table augmented A lot more complicated to fill in the data structure for socket descriptors
Specifying remote end and local end Is the socket listening or connecting Will we use TCP or UDP?
Socket Endpoint Address
Generic endpoint specification
Struct sockaddr { /* struct to hold address */ u_char sa_len; /* total length */ u_short sa_family; /* address family */ char sa_data[14]; /* value of address */ }
TCP/IP protocol endpoint specification Address family: AF_INET All TCP/IP applications should use sockaddr_in instead of the generic one
Struct sockaddr_in { /* struct to hold address */ u_char sa_len; /* total length */ u_short sa_family; /* address family */ u_short sin_port; /* protocol port number */ struct in_addr sin_addr; /* IP address */ char sin_zero[8]; /* unused */ }
Server OS chooses based on routing
AF_INET AF_INET6 AF_UNIX AF_X25
Well-Known or Ephemeral
More Details
Network byte order / Host byte order Why does it matter? Protocol port field of a sockaddr_in structure uses network byte order Utility functions: htons, ntohs, htonl, ntohl Symbolic constants (e.g. AF_INET)
#include <sys/types.h> #include <sys/socket.h>
7
Server
socket() bind() listen() accept()
TCP Client Server
well-known port
Client
socket()
(Block until connection)
Handshake
Data (request)
connect() write()
read() write() read() close() Data (reply)
read()
End-of-File close()
TCP Client
PF_INET PF_INET6 PF_UNIX PF_X25 STREAM DGRAM RAW 0, used by RAW socket
family port
ephemeral port ip addr (routing)
sd = socket (family, type, protocol); sd = connect (sd, server_addr, addr_len);
three way handshaking
addr
CONNECT actions 1. socket is valid 2. fill remote endpoint addr/port 3. choose local endpoint add/port 4. initiate 3-way handshaking
write (sd, *buff, mbytes);
read (sd, *buff, mbytes); close (sd);
Server PORT# IP-ADDR
disconnect sequence
TCP Server
family port addr
bind port # MASTER SOCKET
sd = socket (family, type, protocol);
bind (sd, *server_addr, len);
listen (sd, backlog);
well-known port # INADDR_ANY
1. Turn sd from active to passive 2. Queue length
family port addr
SLAVE SOCKET
ssd = accept (sd, *cliaddr, *len);
three way handshaking
read (ssd, *buff, mbytes);
closes socket for R/W non-blocking attempts to send unsent data socket option SO_LINGER block until data sent
write (ssd, *buff, mbytes);
disconnect sequence
close (ssd);
10
TCP Server
family port family
addr
msock
liste n
accep t
client port/addr
port
addr
ssock read, write
bind
port
three way handshaking
11
Create a socket
socket()
int socket(int family, int type, int protocol);
PF_INET (IPv4), PF_INET6 (IPv6), PF_LOCAL (local Unix), PF_ROUTE (access to routing tables), PF_KEY (encryption) type is one of SOCK_STREAM (TCP), SOCK_DGRAM (UDP) SOCK_RAW (for special IP packets, PING, etc. Must be root) setuid bit (-rws--x--x root 2002 /bin/ping*) protocol is 0 (used for some raw socket options) upon success returns socket descriptor Integer, like file descriptor Return -1 if failure
family is one of
12
Connect to server
int connect(int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);
sockfd is socket descriptor from socket() servaddr is a pointer to a structure with:
connect()
port number and IP address
client doesnt need bind()
addrlen is length of structure
OS will pick ephemeral port
must be specified (unlike bind())
returns socket descriptor if ok, -1 on error
13
Assign a local protocol address (name) to a socket
bind()
int bind(int sockfd, const struct sockaddr *myaddr, socklen_t addrlen);
sockfd is socket descriptor from socket() myaddr is a pointer to address struct with:
port number and IP address
if port is 0, then
if IP address is wildcard: INADDR_ANY (multiple net cards)
host kernel will choose IP address INADDR_ defined in <netinet/in.h> INADDR_ in host byte order => htonl(INADDR_ANY)
host will pick ephemeral port (very rare for server) How do you know assigned port number?
addrlen is length of structure returns 0 if ok, -1 on error
EADDRINUSE (Address already in use)
14
bind()
address and port
process specifies
IP address port
result
kernel chooses IP addr and port
wildcard
wildcard
local IP addr local IP addr
nonzero
0 nonzero
kernel chooses IP, process specifies port
process specifies IP, kernel chooses port process specifies IP and port
15
Change socket state to TCP server
int listen(int sockfd, int backlog);
Sockets default to active (for a client) change to passive so OS will accept connection sockfd is socket descriptor from socket()
listen()
backlog is maximum number of connections that
the server should queue for this socket
historically 5 rarely above 15 on a even moderate Web server!
16
accept()
Return next completed connection
int accept(int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);
sockfd is socket descriptor from socket() cliaddr and addrlen return protocol address from
client returns brand new descriptor, created by OS if used with fork(), can create concurrent server
17
read() and write()
int read (int sockfd, void *buff, size_t mbytes); int write (int sockfd, void *buff, size_t mbytes);
Reading and writing packets Both are system calls
18
close()
Close socket for use
int close(int sockfd);
closes socket for reading/writing returns (doesnt block) attempts to send any unsent data socket option SO_LINGER
Returns -1 if error
block until data sent or discard any remaining data
sockfd is socket descriptor from socket()
19
UDP Client Server
Server
socket()
Client
socket()
well-known port
bind()
recvfrom()
sendto (sd, *buff, mbytes, flag, to, len);
(Block until receive datagram) Data (request)
receivefrom (sd, *buff,
mbytes, flags, *from, *len);
sendto() Data (reply)
close()
20
UDP sending and receiving
sendto(), recvfrom()
int recvfrom(int sockfd, void *buff, size_t mbytes, int flags, struct sockaddr *from, socklen_t *addrlen); int sendto(int sockfd, void *buff, size_t mbytes, int flags, const struct sockaddr *to, socklen_t addrlen);
Similar to read() and write() but need to
specify remote socket address
recvfrom fills in address of where packet came from sento requires address of where sending packet to
21
Connect with UDP
Record address and port of peer datagrams to/from others are not allowed does not do three way handshake, or connection connect a misnomer, here. Should be setpeername() Use send() instead of sendto() Use recv() instead of recvfrom() Can change connect or unconnect by repeating
connect() call
22
recv() and send()
int recv(int mbytes, int int send(int mbytes, int sockfd, void *buff, size_t flags); sockfd, void *buff, size_t flags);
flags
Used for connected sockets (both UDP and TCP)
Same as read() and write() but for
MSG_DONTWAIT (this send non-blocking) MSG_OOB (out of band data) MSG_PEEK (look, but dont remove) MSG_WAITALL (dont give me less than max) MSG_DONTROUTE (bypass routing table)
23