Cs556 3rd Tutorial
Cs556 3rd Tutorial
Sockets Programming in C
using TCP/IP
Introduction
Computer Network
hosts, routers,
communication channels
Host
Router
Communication
channel
Protocol is an agreement
meaning of packets
structure and size of packets
e.g. Hypertext Transfer Protocol
(HTTP)
formatted,
addressed,
transmitted,
routed, and
received at the destination
TCP/IP
*
FTP, SMTP,
Transport Layer
TCP or UDP
Network Layer
IP
Communication
Channels
best-effort protocol
Addresses - IPv4
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,
the first one (for large networks) to three (for small networks) octets can
be used to identify the network, while
the rest of the octets can be used to identify the node on the network.
Range of addresses
Class A:
Class B:
24
Network ID
Host ID
1 0
1.0.0.0 to
127.255.255.255
14
16
Network ID
Host ID
21
Class C:
1 1 0
128.0.0.0 to
191.255.255.255
8
Network ID
Host ID
192.0.0.0 to
223.255.255.255
28
Class D (multicast):
1 1 1 0
Multicast address
27
Class E (reserved):
1 1 1 1 0
unused
224.0.0.0 to
239.255.255.255
240.0.0.0 to
255.255.255.255
TCP vs UDP
no acknowledgements
no retransmissions
out of order, duplicates possible
connectionless, i.e., app indicates destination for each packet
flow control
connection-oriented
bidirectional
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
FTP
HTTP
POP3
Telnet
UDP
TCP
TCP
TCP
TCP
53
21
80
110
23
Berkley Sockets
Application
Socket
Socket
TCP
TCP
IP
Host
CS556 - Distributed Systems
Channel
IP
Router
Tutorial by Eleftherios Kosmas
Channel
IP
Host
10
Sockets
Uniquely identified by
an internet address
an end-to-end protocol (e.g. TCP or UDP)
a port number
0
1
2
Descriptor Table
internal data
structure for file 1
Family: PF_INET
Service: SOCK_STREAM
Local_IP:
Remote_IP:
Local_Port:
Remote_Port:
11
Sockets
Descriptor
references
Applications
UDP sockets
TCP sockets
65535
65535
UDP ports
UDP
TCP
IP
12
Socket Programming
13
Client-Server communication
Server
Client
14
Sockets - Procedures
15
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
16
IPPROTO_TCP IPPROTO_UDP
usually set to 0 (i.e., use default protocol)
) 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
17
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
18
status = close(sockid);
Closing a socket
19
Specifying Addresses
20
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
21
22
23
Datagram socket:
if only sending, no need to bind. The OS finds a port each time the socket
sends a packet
if receiving, need to bind
Stream socket:
24
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
25
26
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
27
connect() is blocking
28
accept()
29
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
30
31
32
Example - Echo
33
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
34
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
35
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
36
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
37
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
38
Server
1.
2.
3.
4.
39
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
40
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
41
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
42
echoStringLen = strlen(echoString);
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
43
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
44
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
45
close(clientSock);
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
46
Client
1.
2.
3.
4.
Server
1.
2.
3.
4.
47
Client
1.
2.
3.
4.
Server
1.
2.
3.
Communicate
48
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl(INADDR_ANY);
echoServAddr.sin_port = htons(echoServPort);
Client
1.
2.
3.
4.
Server
1.
2.
3.
Communicate
49
Client
1.
2.
3.
4.
Server
1.
2.
3.
Communicate
50
Client
1.
2.
3.
4.
Server
1.
2.
3.
Communicate
51
Client
1.
2.
3.
4.
Server
1.
2.
3.
Communicate
52
Client
1.
2.
3.
4.
Server
1.
2.
3.
Communicate
53
Stream
(e.g. TCP)
socket()
Datagram
(e.g. UDP)
Client
Server
socket()
socket()
socket()
bind()
bind()
bind()
Client
listen()
accept()
synchronization
point
connect()
recv()
send()
recvfrom()
sendto()
send()
recv()
sendto()
recvfrom()
close()
close()
close()
close()
54
&
&
e.g. ASCII
the same representation is used to print or display them to screen
allows sending arbitrarily large numbers (at least in principle)
49
55
57
57
56
55
50
48
32
52
55
48
51
52
54
49
53
32
sprintf(msgBuffer, %d %d , x, y);
send(clientSocket, strlen(msgBuffer), 0);
55
Pitfalls
' each digit can be represented using 4 bits, instead of one byte
' it is inconvenient to manipulate numbers
2nd Solution: Sending the values of x and y
56
1st Implementation
typedef struct {
int x,y;
} msgStruct;
msgStruct.x = x; msgStruct.y = y;
send(clientSock, &msgStruct, sizeof(msgStruct), 0);
2nd Implementation
send(clientSock, &x, sizeof(x)), 0);
send(clientSock, &y, sizeof(y)), 0);
2nd implementation
works in any case?
57
Problem:
Big-Endian
machine
128.119.40.12
128
119
40
Little-Endian
machine
12
Tutorial by Eleftherios Kosmas
128
119
12.40.119.128
40
12
58
Big-Endian:
Little-Endian:
59
128
12
119
40
Little-Endian
machine
12
Tutorial by Eleftherios Kosmas
128
12
119
40
128.119.40.12
40 119 128
ntohl
hto
nl
128
119 40
128.119.40.12
Big-Endian
machine
12
60
Example
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");
Server
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);
CS556 - Distributed Systems
61
data structures are maximally aligned, according to the size of the largest native integer
other multibyte fields are aligned to their size, e.g., a four-byte integers address will be
divisible by four
x
x2
y2
4 bytes
2 bytes
4 bytes
2 bytes
4 bytes
x2
2 bytes 2 bytes
typedef struct {
int x;
short x2;
char pad[2];
int y;
short y2;
} msgStruct;
[pad]
y2
4 bytes
2 bytes
typedef struct {
int x;
int y;
short x2;
short y2;
} msgStruct;
62
e.g., msgStruct
63
Socket Options
64
Socket Options
- Table
Fetch and then double the current number of bytes in the sockets
receive buffer
int rcvBufferSize;
int sockOptSize;
66
multiple connections
simultaneous sends and receives
simultaneously doing non-networking processing
67
Non-blocking Sockets
Asynchronous I/O
Timeouts
68
Non-blocking Sockets
MSG_DONTWAIT
69
Signals
the signal is blocked, until the program takes action to allow its delivery
Signals can be nested (i.e., while one is being handled another is delivered)
70
Signals
sa_handler determines which of the first three possibilities occurs when signal is
71
Signals - Example
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
void DieWithError(char *errorMessage);
void InterruptSignalHandler(int signalType);
int main (int argc, char *argv[]) {
struct sigaction handler;
for(;;) pause();
exit(0);
}
72
Asynchronous I/O
the SIGIO signal is delivered to the process, when some I/O-related event
occurs on the socket
Three steps:
/* i. inform the system of the desired disposition of the signal */
struct sigaction handler;
handler.sa_handler = SIGIOHandler;
if (sigfillset(&handler.sa_mask) < 0) DiewithError();
handler.sa_flags = 0;
if (sigaction(SIGIO, &handler, 0) < 0) DieWithError();
/* ii. ensure that signals related to the socket will be delivered to this process */
if (fcntl(sock, F_SETOWN, getpid()) < 0) DieWithError();
/* iii. mark the socket as being primed for asynchronous I/O */
if (fcntl(sock, F_SETFL, O_NONBLOCK | FASYNC) < 0) DieWithError();
73
Timeouts
starts a timer that expires after the specified number of seconds (secs)
returns
the number of seconds remaining until any previously scheduled alarm was
due to be delivered,
74
75
but, the server will respond after it finishes with the first client
& Works well if each client required a small, bounded amount of
work by the server
' otherwise, the clients experience long delays
76
<stdio.h>
<sys/socket.h>
<arpa/inet.h>
<stdlib.h>
<string.h>
<unistd.h>
#define MAXPENDING 5
/*
/*
/*
/*
/*
/*
for
for
for
for
for
for
/*
/*
/*
/*
/*
/*
if (argc != 2) {
/* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]);
exit(1);
}
echoServPort = atoi(argv[1]);
/* First arg:
local port */
77
/*
/*
/*
/*
78
79
int fork();
a new process is created, identical to the calling process, except for its
process ID and the return value it receives from fork()
returns 0 to child process, and the process ID of the new child to
parent
Caution:
when a child process terminates, it does not automatically disappears
use waitpid() to parent in order to harvest zombies
80
/* for waitpid() */
/*
/*
/*
/*
/*
if (argc != 2) {
/* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]);
exit(1);
}
echoServPort = atoi(argv[1]);
/* First arg: local port */
servSock = CreateTCPServerSocket(echoServPort);
for (;;) { /* Run forever */
clntSock = AcceptTCPConnection(servSock);
if ((processID = fork()) < 0) DieWithError (fork() failed); /* Fork child process */
else if (processID = 0) {
/* This is the child process */
close(servSock);
/* child closes listening socket */
HandleTCPClient(clntSock);
exit(0);
/* child process terminates */
}
close(clntSock);
childProcCount++;
...
81
}
/* NOT REACHED */
}
82
83
struct ThreadArgs {
int clntSock;
};
/*
/*
/*
/*
/*
if (argc != 2) {
/* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <Server Port>\n", argv[0]);
exit(1);
}
echoServPort = atoi(argv[1]);
/* First arg: local port */
servSock = CreateTCPServerSocket(echoServPort);
for (;;) { /* Run forever */
clntSock = AcceptTCPConnection(servSock);
/* Create separate memory for client argument */
if ((threadArgs = (struct ThreadArgs *) malloc(sizeof(struct ThreadArgs)))) == NULL) DieWithError();
threadArgs -> clntSock = clntSock;
/* Create client thread */
if (pthread_create (&threadID, NULL, ThreadMain, (void *) threadArgs) != 0) DieWithError();
}
/* NOT REACHED */
}
84
85
Multitasking - Constrained
86
Multitasking - Constrained
- Example: echo using stream socket
void ProcessMain(int servSock);
/*
/*
/*
/*
/*
if (argc != 3) {
/* Test for correct number of arguments */
fprintf(stderr,"Usage: %s <SERVER PORT> <FORK LIMIT>\n", argv[0]);
exit(1);
}
echoServPort = atoi(argv[1]);
processLimit = atoi(argv[2]);
servSock = CreateTCPServerSocket(echoServPort);
for (processCt=0; processCt < processLimit; processCt++)
if ((processID = fork()) < 0) DieWithError("fork() failed");
else if (processID == 0) ProcessMain(servSock);
exit(0);
}
void ProcessMain(int servSock) {
int clntSock;
87
Multiplexing
88
Multiplexing
FD_ZERO
FD_CLR
FD_SET
FD_ISSET
(fd_set *descriptorVector);
(int descriptor, fd_set *descriptorVector);
(int descriptor, fd_set *descriptorVector);
(int descriptor, fd_set *descriptorVector);
struct timeval {
time_t tv_sec;
time_t tv_usec;
};
CS556 - Distributed Systems
/* seconds */
/* microseconds */
89
/*
/*
/*
/*
/*
/*
/*
/*
/*
if (argc < 3) {
/* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <Timeout (secs.)> <Port 1> ...\n", argv[0]);
exit(1);
}
timeout = atol(argv[1]);
noPorts = argc - 2;
servSock = (int *) malloc(noPorts * sizeof(int)); /* Allocate list of sockets for incoming connections */
maxDescriptor = -1;
/* Initialize maxDescriptor for use by select() */
for (port = 0; port < noPorts; port++) {
/* Create list of ports and sockets to handle ports */
portNo = atoi(argv[port + 2]);
/* Add port to port list. Skip first two arguments */
servSock[port] = CreateTCPServerSocket(portNo); /* Create port socket */
if (servSock[port] > maxDescriptor)
maxDescriptor = servSock[port];
}
...
90
/* Close sockets */
/* Free list of sockets */
91
Multiple Recipients
92
Directed broadcast:
why?
93
94
Useful Functions
95
Useful Functions
96
97
98
99
100