TCP/IP Sockets in C
TCP/IP Sockets in C
Sockets Programming in C
using TCP/IP
Professor: Panagiota Fatourou
TA: Eleftherios Kosmas
CSD - May 2012
Introduction
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 2
Computer Network
O hosts, routers,
communication channels
Hosts run applications
Routers forward information
Packets: sequence of bytes
O contain control information
O e.g. destination host
Protocol is an agreement
O meaning of packets
O structure and size of packets
e.g. Hypertext Transfer Protocol
(HTTP)
Host
Router
Communication
channel
Protocol Families - TCP/IP
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 3
Several protocols for different problems
Protocol Suites or Protocol Families: TCP/IP
TCP/IP provides end-to-end connectivity specifying how data
should be
O formatted,
O addressed,
O transmitted,
O routed, and
O received at the destination
can be used in the internet and in stand-alone private networks
it is organized into layers
TCP/IP
* image is taken from http://en.wikipedia.org/wiki/TCP/IP_model
*
Communication
Channels
Network Layer
IP
Transport Layer
TCP or UDP
FTP, SMTP,
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 4
Internet Protocol (IP)
provides a datagram service
O packets are handled and delivered
independently
best-effort protocol
O may loose, reorder or duplicate
packets
each packet must contain an IP
address of its destination
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 5
Addresses - IPv4
7 24
Class A: 0 Network ID Host ID
14 16
Class B: 1 0 Network ID Host ID
21 8
Class C: 1 1 0 Network ID Host ID
28
Class D (multicast): 1 1 1 0 Multicast address
27
Class E (reserved): 1 1 1 1 unused 0
1.0.0.0 to
127.255.255.255
128.0.0.0 to
191.255.255.255
192.0.0.0 to
223.255.255.255
224.0.0.0 to
239.255.255.255
240.0.0.0 to
255.255.255.255
Range of addresses
The 32 bits of an IPv4 address are broken into 4 octets, or 8 bit fields
(0-255 value in decimal notation).
For networks of different size,
O the first one (for large networks) to three (for small networks) octets can
be used to identify the network, while
O the rest of the octets can be used to identify the node on the network.
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 6
Local Area Network Addresses - IPv4
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 7
TCP vs UDP
Both use port numbers
O application-specific construct serving as a communication endpoint
O 16-bit unsigned integer, thus ranging from 0 to 65535
to provide end-to-end transport
UDP: User Datagram Protocol
O no acknowledgements
O no retransmissions
O out of order, duplicates possible
O connectionless, i.e., app indicates destination for each packet
TCP: Transmission Control Protocol
O reliable byte-stream channel (in order, all arrive, no duplicates)
similar to file I/O
O flow control
O connection-oriented
O bidirectional
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 8
TCP vs UDP
TCP is used for services with a large data capacity, and a persistent
connection
UDP is more commonly used for quick lookups, and single use
query-reply actions.
Some common examples of TCP and UDP with their default ports:
DNS lookup UDP 53
FTP TCP 21
HTTP TCP 80
POP3 TCP 110
Telnet TCP 23
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 9
Berkley Sockets
Universally known as Sockets
It is an abstraction through which an
application may send and receive data
Provide generic access to interprocess
communication services
O e.g. IPX/SPX, Appletalk, TCP/IP
Standard API for networking
Host
Application
Socket
TCP
IP
Host
Application
Socket
TCP
IP
Router
IP
Channel
Channel
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 10
Sockets
Uniquely identified by
O an internet address
O an end-to-end protocol (e.g. TCP or UDP)
O a port number
Two types of (TCP/IP) sockets
O Stream sockets (e.g. uses TCP)
provide reliable byte-stream service
O Datagram sockets (e.g. uses UDP)
provide best-effort datagram service
messages up to 65.500 bytes
Socket extend the convectional UNIX I/O facilities
O file descriptors for network communication
O extended the read and write system calls
0
1
2
internal data
structure for file 1
Family: PF_INET
Service: SOCK_STREAM
Local_IP:
Remote_IP:
Remote_Port:
Local_Port:
Descriptor Table
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 11
Sockets
TCP UDP
IP
1 2 65535
1 2 65535
Applications
TCP sockets
UDP sockets
TCP ports UDP ports
Descriptor
references
Sockets bound to ports
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 12
Socket Programming
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 13
Client-Server communication
Server
O passively waits for and responds to clients
O passive socket
Client
O initiates the communication
O must know the address and the port of the server
O active socket
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 14
Sockets - Procedures
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 15
Client - Server Communication - Unix
socket()
bind()
listen()
accept()
recv()
send()
close()
Server
socket()
connect()
send()
recv()
close()
Client
synchronization
point
Stream
(e.g. TCP)
socket()
bind()
recvfrom()
sendto()
close()
Server
socket()
sendto()
recvfrom()
close()
Client
Datagram
(e.g. UDP)
bind()
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 16
Socket creation in C: socket ( )
int sockid = socket(family, type, protocol);
O sockid: socket descriptor, an integer (like a file-handle)
O family: integer, communication domain, e.g.,
PF_INET, IPv4 protocols, Internet addresses (typically used)
PF_UNIX, Local communication, File addresses
O type: communication type
SOCK_STREAM - reliable, 2-way, connection-based service
SOCK_DGRAM - unreliable, connectionless, messages of maximum length
O protocol: specifies protocol
IPPROTO_TCP IPPROTO_UDP
usually set to 0 (i.e., use default protocol)
O upon failure returns -1
NOTE: socket call does not specify where data will be coming from,
nor where it will be going to it just creates the interface!
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 17
Client - Server Communication - Unix
socket()
bind()
listen()
accept()
recv()
send()
close()
Server
socket()
connect()
send()
recv()
close()
Client
synchronization
point
Stream
(e.g. TCP)
socket()
bind()
recvfrom()
sendto()
close()
Server
socket()
sendto()
recvfrom()
close()
Client
Datagram
(e.g. UDP)
bind()
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 18
Socket close in C: cl ose( )
When finished using a socket, the socket should be closed
status = close(sockid);
O sockid: the file descriptor (socket being closed)
O status: 0 if successful, -1 if error
Closing a socket
O closes a connection (for stream socket)
O frees up the port used by the socket
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 19
Specifying Addresses
Socket API defines a generic data type for addresses:
Particular form of the sockaddr used for TCP/IP addresses:
Important: sockaddr_in can be casted to a sockaddr
struct sockaddr {
unsigned short sa_family; /* Address family (e.g. AF_INET) */
char sa_data[14]; /* Family-specific address information */
}
struct in_addr {
unsigned long s_addr; /* Internet address (32 bits) */
}
struct sockaddr_in {
unsigned short sin_family; /* Internet protocol (AF_INET) */
unsigned short sin_port; /* Address port (16 bits) */
struct in_addr sin_addr; /* Internet address (32 bits) */
char sin_zero[8]; /* Not used */
}
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 20
Client - Server Communication - Unix
socket()
bind()
listen()
accept()
recv()
send()
close()
Server
socket()
connect()
send()
recv()
close()
Client
synchronization
point
Stream
(e.g. TCP)
socket()
bind()
recvfrom()
sendto()
close()
Server
socket()
sendto()
recvfrom()
close()
Client
Datagram
(e.g. UDP)
bind()
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 21
Assign address to socket: bi nd( )
associates and reserves a port for use by the socket
int status = bind(sockid, &addrport, size);
O sockid: integer, socket descriptor
O addrport: struct sockaddr, the (IP) address and port of the machine
for TCP/IP server, internet address is usually set to INADDR_ANY, i.e.,
chooses any incoming interface
O size: the size (in bytes) of the addrport structure
O status: upon failure -1 is returned
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 22
bi nd( ) - Example with TCP
int sockid;
struct sockaddr_in addrport;
sockid = socket(PF_INET, SOCK_STREAM, 0);
addrport.sin_family = AF_INET;
addrport.sin_port = htons(5100);
addrport.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sockid, (struct sockaddr *) &addrport, sizeof(addrport))!= -1) {
}
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 23
Skipping the bi nd( )
bind can be skipped for both types of sockets
Datagram socket:
O if only sending, no need to bind. The OS finds a port each time the socket
sends a packet
O if receiving, need to bind
Stream socket:
O destination determined during connection setup
O dont need to know port sending from (during connection setup, receiving
end is informed of port)
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 24
Client - Server Communication - Unix
socket()
bind()
listen()
accept()
recv()
send()
close()
Server
socket()
connect()
send()
recv()
close()
Client
synchronization
point
Stream
(e.g. TCP)
socket()
bind()
recvfrom()
sendto()
close()
Server
socket()
sendto()
recvfrom()
close()
Client
Datagram
(e.g. UDP)
bind()
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 25
Assign address to socket: bi nd( )
Instructs TCP protocol implementation to listen for connections
int status = listen(sockid, queueLimit);
O sockid: integer, socket descriptor
O queuelen: integer, # of active participants that can wait for a connection
O status: 0 if listening, -1 if error
l i st en( ) is non-blocking: returns immediately
The listening socket (sockid)
O is never used for sending and receiving
O is used by the server only as a way to get new sockets
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 26
Client - Server Communication - Unix
socket()
bind()
listen()
accept()
recv()
send()
close()
Server
socket()
connect()
send()
recv()
close()
Client
synchronization
point
Stream
(e.g. TCP)
socket()
bind()
recvfrom()
sendto()
close()
Server
socket()
sendto()
recvfrom()
close()
Client
Datagram
(e.g. UDP)
bind()
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 27
Establish Connection: connect ( )
The client establishes a connection with the server by calling
connect ( )
int status = connect(sockid, &foreignAddr, addrlen);
O sockid: integer, socket to be used in connection
O foreignAddr: struct sockaddr: address of the passive participant
O addrlen: integer, sizeof(name)
O status: 0 if successful connect, -1 otherwise
connect ( ) is blocking
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 28
Incoming Connection: accept ( )
The server gets a socket for an incoming client connection by calling
accept ( )
int s = accept(sockid, &clientAddr, &addrLen);
O s: integer, the new socket (used for data-transfer)
O sockid: integer, the orig. socket (being listened on)
O clientAddr: struct sockaddr, address of the active participant
filled in upon return
O addrLen: sizeof(clientAddr): value/result parameter
must be set appropriately before call
adjusted upon return
accept ( )
O is blocking: waits for connection before returning
O dequeues the next connection on the queue for socket (sockid)
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 29
Client - Server Communication - Unix
socket()
bind()
listen()
accept()
recv()
send()
close()
Server
socket()
connect()
send()
recv()
close()
Client
synchronization
point
Stream
(e.g. TCP)
socket()
bind()
recvfrom()
sendto()
close()
Server
socket()
sendto()
recvfrom()
close()
Client
Datagram
(e.g. UDP)
bind()
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 30
Exchanging data with stream socket
int count = send(sockid, msg, msgLen, flags);
O msg: const void[], message to be transmitted
O msgLen: integer, length of message (in bytes) to transmit
O flags: integer, special options, usually just 0
O count: # bytes transmitted (-1 if error)
int count = recv(sockid, recvBuf, bufLen, flags);
O recvBuf: void[], stores received bytes
O bufLen: # bytes received
O flags: integer, special options, usually just 0
O count: # bytes received (-1 if error)
Calls are blocking
O returns only after data is sent / received
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 31
Exchanging data with datagram socket
int count = sendto(sockid, msg, msgLen, flags,
&foreignAddr, addrlen);
O msg, msgLen, flags, count: same with send( )
O foreignAddr: struct sockaddr, address of the destination
O addrLen: sizeof(foreignAddr)
int count = recvfrom(sockid, recvBuf, bufLen,
flags, &clientAddr, addrlen);
O recvBuf, bufLen, flags, count: same with r ecv( )
O clientAddr: struct sockaddr, address of the client
O addrLen: sizeof(clientAddr)
Calls are blocking
O returns only after data is sent / received
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 32
Example - Echo
A client communicates with an echo server
The server simply echoes whatever it receives back to the client
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 33
Example - Echo using stream socket
Client
1. Create a TCP socket
2. Establish connection
3. Communicate
4. Close the connection
Server
1. Create a TCP socket
2. Assign a port to socket
3. Set socket to listen
4. Repeatedly:
a. Accept new connection
b. Communicate
c. Close the connection
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 34
The server starts by getting ready to receive client connections
Example - Echo using stream socket
Client
1. Create a TCP socket
2. Establish connection
3. Communicate
4. Close the connection
Server
1. Create a TCP socket
2. Assign a port to socket
3. Set socket to listen
4. Repeatedly:
a. Accept new connection
b. Communicate
c. Close the connection
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 35
/* Create socket for incoming connections */
if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
Example - Echo using stream socket
Client
1. Create a TCP socket
2. Establish connection
3. Communicate
4. Close the connection
Server
1. Create a TCP socket
2. Assign a port to socket
3. Set socket to listen
4. Repeatedly:
a. Accept new connection
b. Communicate
c. Close the connection
echoServAddr.sin_family = AF_INET; /* Internet address family */
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
echoServAddr.sin_port = htons(echoServPort); /* Local port */
if (bind(servSock, (struct sockaddr *) &echoServAddr, sizeof(echoServAddr)) < 0)
DieWithError("bind() failed");
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 36
Example - Echo using stream socket
Client
1. Create a TCP socket
2. Establish connection
3. Communicate
4. Close the connection
Server
1. Create a TCP socket
2. Assign a port to socket
3. Set socket to listen
4. Repeatedly:
a. Accept new connection
b. Communicate
c. Close the connection
/* Mark the socket so it will listen for incoming connections */
if (listen(servSock, MAXPENDING) < 0)
DieWithError("listen() failed");
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 37
Example - Echo using stream socket
Client
1. Create a TCP socket
2. Establish connection
3. Communicate
4. Close the connection
Server
1. Create a TCP socket
2. Assign a port to socket
3. Set socket to listen
4. Repeatedly:
a. Accept new connection
b. Communicate
c. Close the connection
for (;;) /* Run forever */
{
clntLen = sizeof(echoClntAddr);
if ((clientSock=accept(servSock,(struct sockaddr *)&echoClntAddr,&clntLen))<0)
DieWithError("accept() failed");
...
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 38
Example - Echo using stream socket
Client
1. Create a TCP socket
2. Establish connection
3. Communicate
4. Close the connection
Server
1. Create a TCP socket
2. Assign a port to socket
3. Set socket to listen
4. Repeatedly:
a. Accept new connection
b. Communicate
c. Close the connection
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 39
Server is now blocked waiting for connection from a client
msgStruct.x = x; msgStruct.y = y;
send(clientSock, &msgStruct, sizeof(msgStruct), 0);
send(clientSock, &x, sizeof(x)), 0);
send(clientSock, &y, sizeof(y)), 0);
1
st
Implementation
2
nd
Implementation
2
nd
implementation
works in any case?
Constructing Messages - Encoding Data
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 57
Address and port are stored as integers
O u_short sin_port; (16 bit)
O in_addr sin_addr; (32 bit)
Problem:
O different machines / OSs use different word orderings
little-endian: lower bytes first
big-endian: higher bytes first
O these machines may communicate with one another over the
network
128.119.40.12
128 119 40 12
12.40.119.128
128 119 40 12
Big-Endian
machine
Little-Endian
machine
Constructing Messages - Byte Ordering
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 58
Big-Endian:
Little-Endian:
Constructing Messages - Byte Ordering
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 59
Constructing Messages - Byte Ordering -
Solution: Network Byte Ordering
Host Byte-Ordering: the byte ordering used by a host (big or little)
Network Byte-Ordering: the byte ordering used by the network
always big-endian
u_long htonl(u_long x);
u_short htons(u_short x);
u_long ntohl(u_long x);
u_short ntohs(u_short x);
On big-endian machines, these routines do nothing
On little-endian machines, they reverse the byte order
128.119.40.12
128 119 40 12
128.119.40.12
128 119 40 12
Big-Endian
machine
Little-Endian
machine
h
t
o
n
l
n
t
o
h
l
128 119 40 12
128 119 40 12
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 60
unsigned short clientPort, message; unsigned int messageLenth;
servPort = 1111;
message = htons(clientPort);
messageLength = sizeof(message);
if (sendto( clientSock, message, messageLength, 0,
(struct sockaddr *) &echoServAddr, sizeof(echoServAddr))
!= messageLength)
DieWithError("send() sent a different number of bytes than expected");
Client
unsigned short clientPort, rcvBuffer;
unsigned int recvMsgSize ;
if ( recvfrom(servSock, &rcvBuffer, sizeof(unsigned int), 0),
(struct sockaddr *) &echoClientAddr, sizeof(echoClientAddr)) < 0)
DieWithError(recvfrom() failed");
clientPort = ntohs(rcvBuffer);
printf (Clients port: %d, clientPort);
Server
Constructing Messages - Byte Ordering -
Example
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 61
consider the following 12 byte structure
After compilation it will be a 14 byte structure!
Why? Alignment!
Remember the following rules:
O data structures are maximally aligned, according to the size of the largest native integer
O other multibyte fields are aligned to their size, e.g., a four-byte integers address will be
divisible by four
This can be avoided
O include padding to data structure
O reorder fields
Constructing Messages - Alignment and Padding
typedef struct {
int x;
short x2;
int y;
short y2;
} msgStruct;
x x2 y y2
4 byt es 2 byt es 4 byt es 2 byt es
x x2 y y2
4 byt es 2 byt es 4 byt es 2 byt es
[pad]
2 byt es
typedef struct {
int x;
short x2;
char pad[2];
int y;
short y2;
} msgStruct;
typedef struct {
int x;
int y;
short x2;
short y2;
} msgStruct;
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 62
Framing is the problem of formatting the information so that the
receiver can parse messages
Parse means to locate the beginning and the end of message
This is easy if the fields have fixed sizes
O e.g., msgSt r uct
For text-string representations is harder
O Solution: use of appropriate delimiters
O caution is needed since a call of r ecv may return the messages sent by
multiple calls of send
Constructing Messages - Framing and Parsing
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 63
Socket Options
get sockopt and set sockopt allow socket options values to be
queried and set, respectively
int getsockopt (sockid, level, optName, optVal,
optLen);
O sockid: integer, socket descriptor
O level: integer, the layers of the protocol stack (socket, TCP, IP)
O optName: integer, option
O optVal: pointer to a buffer; upon return it contains the value of the
specified option
O optLen: integer, in-out parameter
it returns -1 if an error occured
int setsockopt (sockid, level, optName, optVal,
optLen);
O optLen is now only an input parameter
CS556 - Distributed Systems Tutorial by Eleftherios Kosmas 64
Socket Options
- Table
Socket Options - Example
Fetch and then double the current number of bytes in the sockets
receive buffer
int rcvBufferSize;
int sockOptSize;