Interprocess Communication: Sockets
1. Background [SGG 8/E]
2. A First Look at TCP/IP Communication
3. Connection Setup for TCP Sockets
Copyright By PowCoder代写 加微信 powcoder
4. Examples of Socket Support Functions
5. Basic Socket Operations
6. Sending and Receiving
7. Example: A Simple Client
8. Socket Operations for Servers
9. Example: A Simple Concurrent Server
CMPUT 379 (E.S. Elmallah)
1. Background
Sockets have been first introduced in Unix BSD (4.2) to support the ARPA network.
Nowadays, the sockets API is an industry standard software abstraction.
The API enables the use of many IPC protocols and methods, organized as “protocol families”: e.g.
o AF-INET: IPv4 protocols
o AF_INET6: IPv6 protocols
o AF_ROUTE: Access to kernel routing information o AF_KEY: Security protocols
o AF_LOCAL: Unix domain IPC (same host peers), and “protocol types” within each “family”.
CMPUT 379 (E.S. Elmallah)
The API provides uniform interface to all such services using file descriptors, e.g.
UDP provides unreliable connectionless byte stream
TCP provides reliable connection-oriented byte stream
bundled with flow control and congestion control
CMPUT 379 (E.S. Elmallah)
int sockfd;
sockfd= socket (AF_INET, SOCK_STREAM, 0); // for TCP socket sockfd= socket (AF_INET, SOCK_DGRAM, 0); // for UDP socket sockfd= socket (AF_INET, SOCK_RAW, 0); // for routing info
We’ll focus on TCP sockets host or
process socket
controlled by app developer
host or server
process socket
TCP with buffers, variables
controlled by OS
CMPUT 379 (E.S. Elmallah)
TCP with buffers, variables
2. A First Look at TCP/IP Communication
Application data is carried inside a TCP (or UDP) segment that is carried inside an IP segment.
CMPUT 379 (E.S. Elmallah)
Network Layer Addresses
o Currently, many Internet hosts and routers are identified by
• 32-bit (IPv4) addresses: e.g., 129.128.5.145
• Human readable names: e.g., gpu.srv.ualberta.ca
o Each networked interface card in each host is
assigned an IP address
o To enable routing, IP addresses form a hierarchy
(like, e.g., “country, city, street” addresses).
o A special address: 127.0.0.1 ≡ the local host (loop back) connection
• useful in program development
CMPUT 379 (E.S. Elmallah)
The Domain Name Service (DNS)
o a global distributed database system for resolving
hostname-IP address mappings
o DNS also provides other services: e.g.,
• host aliasing: e.g., www.ibm.com is really servereast.backup2.ibm.com
• mail server aliasing: same as above (e.g., hotmail.com may be an alias for relay1.west- coast.hotmial.com)
CMPUT 379 (E.S. Elmallah)
TransportLayerAddresses
o Port numbers (16 bits), rather than PIDs, are used for
process-to-process communication.
o Port numbers are managed by the Internet Assigned
Numbers Authority (IANA)
o well-known ports: 0 through 1023
• reserved statically for well-known services: e.g., ‘daytime 13/tcp’, ‘nameserver 42/udp’, `www 80/tcp’, ‘ftp 21/tcp’.
o registered ports: 1024 through 49151
• Not controlled by IANA, but kept track of by the IANA
as a convenience to the community
o dynamic or private ports: 49152 to 65535 (called ephemeral ports)
CMPUT 379 (E.S. Elmallah)
Delivering received segments:
o each TCP socket is identified by 4-tuple:
(source IP address, source port number, dest IP address, dest port number)
CMPUT 379 (E.S. Elmallah)
Assigning a local protocol address to a socket ≡ specifying source IP address and port #
Assigning a remote protocol address to a socket ≡ specifying destination IP address and port #
In some cases, the OS fills the information for us
CMPUT 379 (E.S. Elmallah)
3. Connection Setup for TCP Sockets
The required sequence of calls is asymmetric:
CMPUT 379 (E.S. Elmallah)
4. Examples of Socket Support Functions
Numerous support functions are needed to provide: o mapping binary numbers to network byte order o manipulation of IP addresses
o accessing the domain name system
o obtaining information about hosts
o obtaining information about networks
o obtaining information about protocols
o obtaining information about network services
CMPUT 379 (E.S. Elmallah)
Mapping Numbers to Network Byte Order
o TCP/IP specifies a standard representation for binary
integers used in protocol headers.
o The representation (a big endian) is known as
network byte order.
o support functions:
• htonl : converts host to network, long integer
• htons : converts host to network, short integer • ntohl : converts network to host, long integer
• ntohs : converts network to host, short integer
CMPUT 379 (E.S. Elmallah)
Manipulation of IP addresses
o Convert IP addresses between ASCII strings (e.g.,
“127.0.0.1”) and network byte ordered binary values o Older functions: inet_aton(), inet_ntoa(), inet_addr()
o Newer functions: inet_pton() and inet_ntop()
o Example:
char inStr[30]= “127.0.0.1”; char outStr[30]; int ip_addr;
if ( inet_pton (AF_INET, inStr, &ip_addr) < 1 ) error ....
if ( inet_ntop (AF_INET, &ip_addr, outStr, sizeof(outStr)) == NULL) error ... printf ("IP addr= [%s]: host byte-order 0x%x, network byte-order 0x%x \n", outStr, ip_addr, htonl(ip_addr));
On a little-endian CPU, gives:
IP addr= [127.0.0.1]: host byte-order 0x100007f, network byte-order 0x7f000001
CMPUT 379 (E.S. Elmallah)
Obtaining Information About Hosts, e.g.
o Old: gethostbyname() and gethostbyaddr()
o POSIX: getaddrinfo()
are used to retrieve information either from a DNS server, or a local database file.
o Example:
where NAME specifies a host address (e.g., gpu.srv.ualberta.ca) o and
#include
struct hostent *gethostbyname (char *NAME);
struct hostent {
char char int int char
*h_name; **h_aliases;
h_addrtype;
h_length; **h_addr_list;
// canonical name of host
// alias list
// host address type: AF_INET // length of address: 4 bytes // list of addresses
#define h_addr h_addr_list[0] // for backward compatibility
CMPUT 379 (E.S. Elmallah)
Obtaining Information About Services
o E.g., getservbyname() and getservbyport() are used
to get information about well-known services. o Example:
o Obtains information of service NAME that runs on the specified PROTOCOL (e.g., tcp, udp, etc.)
#include
struct servent *getservbyname (char *NAME, char *PROTOCOL);
struct servent {
char char int char
*s_name; **s_aliases; s_port; *s_proto;
// official name of service // alias list
// port service resides at // protocol to use
CMPUT 379 (E.S. Elmallah)
5. Basic Socket Operations Creating a Socket
o DOMAIN= AF_INET selects the IPv4 protocol family (i.e., the Internet domain).
o Other values: AF_INET6, AF_LOCAL, AF_APPLETALK, etc.
o TYPE= SOCK_STREAM selects the TCP protocol.
o PROTOCOL= 0 allows the system to select a protocol that supports the requested socket type.
o OS returns a file descriptor for a socket, or ’-1’ if an error occurs.
#include
int socket (int DOMAIN, int TYPE, int PROTOCOL);
CMPUT 379 (E.S. Elmallah)
Socket Address Structure (SA)
o ’C struct’ carrying information between processes and kernel: e.g., sockaddr_in{}, sockaddr_in6{}, sockaddr_un{}, sockadd_dl{}
o Of particular interest to us is sockaddr_in{} :
CMPUT 379 (E.S. Elmallah)
POSIX definition:
struct sockaddr_in {
sa_family_t
struct in_addr sin_addr; … …
// length of structure (16 bytes)
// 2-byte type field (AF_INET)
// 16-bit TCP or UDP port number // 32 bit IPv4 address
// unused space
sin_len; sin_family; sin_port;
struct in_addr{
in_addr_t s_addr; // 32-bit IPv4 address
// network byte ordered
CMPUT 379 (E.S. Elmallah)
Typically, calls pass a pointer to a SA structure, along with the length of the structure, e.g.
o Note: sometimes the length of a struct is used as a value-result argument (i.e., specifies both an input and output values)
CMPUT 379 (E.S. Elmallah)
#define SA struct sockaddr
struct sockaddr_in serv;
bind (sockfd, (SA *) &serv, sizeof(serv));
struct sockaddr_un cli;
len= sizeof(cli);
getpeername (unixfd, (SA *) &cli, &len);
// Unix domain
// len is a value
// len may have changed
Specifying a Remote Address
o A client program specifies a server’s IP address and port number (i.e., assigns a remote protocol address to a socket) using connect()
int connect (int sfd, SA *NAME, size of NAME);
• sfd is a socket descriptor obtained by calling socket() • NAME stores server’s IP address and port #
• On error, return ’-1’ and set errno
CMPUT 379 (E.S. Elmallah)
o Example:
struct sockaddr_in serv;
memset ((char *) &serv, 0, sizeof (serv)); serv.sin_family= AF_NET;
If (inet_pton(AF_INET, argv[1], &serv.sin_addr) < 1)
//e.g., argv[1]= 127.0.0.1
error .....
serv.sin_port= htons (13); // well-known port for daytime If (connect (sfd, (SA *) &serv, sizeof (serv)) < 0)
error ....
o Connection Establishment: if the socket is of type SOCK_STREAM, connect() attempts to make a connection to another socket specified by NAME
CMPUT 379 (E.S. Elmallah)
Specifying a Local Address
o A server program specifies its port number and IP address (i.e., assigns a local protocol address to a socket) using bind():
int bind (int sfd, SA *NAME, size of NAME); o Example:
struct sockaddr_in serv; int listenfd;
memset ((char *) &serv, 0, sizeof (serv)); serv.sin_family= AF_NET; serv.sin_addr.s_addr= htonl (INADDR_ANY); serv.sin_port= htons (13);
// well-known port for daytime
If (bind (listenfd, (SA *) &serv, sizeof (serv)) < 0) error .... CMPUT 379 (E.S. Elmallah)
o Listening (or Management) Socket: if the socket is of type SOCK_STREAM, bind() makes the socket a listening socket that can be used in a call to accept() (to be discussed shortly)
o Note: typically, a client program does not specify a local protocol address explicitly:
• if the socket is unbound at the time of connect(), the system automatically selects and binds a name to the socket
CMPUT 379 (E.S. Elmallah)
6. Sending and Receiving
read(), write():
o use 3 parameters (e.g., read(connfd, &buf &length))
o used mainly with TCP sockets
o with TCP, a zero return from read() means the other host has closed connection
o Can be used with poll() and select()
CMPUT 379 (E.S. Elmallah)
o Caveat: With pipes, FIFOs, and TCP sockets
• a read operation may return less than asked for, and
• a write operation can also return less than we specified.
o That is, TCP may choose to break a block of data into pieces and transmit each piece in a separate segment
CMPUT 379 (E.S. Elmallah)
How to handle?
o For line-oriented I/O, we can use the Standard I/O
library (turn a file descriptor into a FILE pointer): e.g.,
char line[MAXLINE]; FILE *fpin, *fpout;
fpin = fdopen (sockfd, “r”); fpout = fdopen (sockfd, “w”);
while (fgets (line, MAXLINE, fpin) != NULL) fputs (line, fpout);
// echo each string
CMPUT 379 (E.S. Elmallah)
o Else, implement readn() and writen() described in [APUE 3/E] Section 14.7
int n= 128; //expecting a message of length 128 bytes nr= readn (sfd, &buf, n); // On successful return,
// we get exactly 128 bytes read
CMPUT 379 (E.S. Elmallah)
recv(), send():
o first 3 parameters as in read() and write(), 4th parameter is flags passed to the kernel (persist for just one I/O)
o Some flags: MSG_DONTROUTE, MSG_OOB, MSG_PEEK, etc.
CMPUT 379 (E.S. Elmallah)
recvfrom(), sendto():
o first 4 parameters as in recv() and send(),
o 5th and 6th parameters convey information about a SA structure.
o used with UDP sockets
o Note: for UDP sockets it is OK to send no data (i.e., a
UDP datagram with header but no data).
o also, a zero return value form recvfrom() does not mean peer has closed connection
CMPUT 379 (E.S. Elmallah)
7. Example: A Simple Client
refer to file ’gs_client.c’ (get service client)
o Usage: gs_client hostname tcp_service
the program sets a CPU limit on the program (a good practice for lab assignments)
the program uses poll() for nonblocking reads from the server and the keyboard (with timeout= 0)
the example also illustrates the use of STREAM I/O functions with sockets
CMPUT 379 (E.S. Elmallah)
#include
#include
#include
CMPUT 379 (E.S. Elmallah)
int main (int argc, char *argv[]) {
struct rlimit
struct pollfd struct sockaddr_in struct servent struct hostent
i, rval, timeout, s; buf[80]; cpuLimit;
pfd[2]; server;
// service entity // host entity
CMPUT 379 (E.S. Elmallah)
// check for at least two arguments if (argc < 3) {
fprintf (stderr, "Usage: %s hostname service \n", argv[0]); fprintf (stderr, " e.g., %s gpu.srv.ualberta.ca ssh\n",
exit (1); }
CMPUT 379 (E.S. Elmallah)
// set a cpu limit
cpuLimit.rlim_cur= cpuLimit.rlim_max= CPU_LIMIT; if (setrlimit (RLIMIT_CPU, &cpuLimit) < 0 ) {
fprintf (stderr, "%s: can't set cpu limit \n", argv[0]); exit (1);
getrlimit (RLIMIT_CPU, &cpuLimit);
printf ("cpuLimit: current (soft)= %ld, maximum (hard)= %ld \n",
cpuLimit.rlim_cur, cpuLimit.rlim_max);
CMPUT 379 (E.S. Elmallah)
// locate the service definition (e.g., “http”, or “ssh”) sp= getservbyname (argv[2], "tcp");
if (sp == (struct servent *) NULL) {
fprintf (stderr, "%s: unknown tcp service \n", argv[0]); exit (1);
// lookup the specified host
hp= gethostbyname(argv[1]);
if (hp == (struct hostent *) NULL) {
fprintf (stderr, "%s: unknown host '%s'\n", argv[0], argv[1]);
exit (1); }
CMPUT 379 (E.S. Elmallah)
// put the host's address, and type into a socket structure;
// first, clear the structure, then fill in with the IP address
// of the foreign host, and the port number at which the remote // server listens
memset ((char *) &server, 0, sizeof server); server.sin_family= hp->h_addrtype;
// In the next statements, there is no worry about network byte
// order since we copy from another network struct memcpy ((char *) &server.sin_addr, hp->h_addr, hp->h_length); server.sin_port= sp->s_port;
CMPUT 379 (E.S. Elmallah)
// create a socket, and initiate a connection
if ( (s = socket (hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
fprintf (stderr, "%s: socket \n", argv[0]); exit (1);
// if the socket is unbound at the time of connect(); the system // automatically selects and binds a name to the socket
if (connect (s, (struct sockaddr *) &server, sizeof server) < 0) {
fprintf (stderr, "%s: connect\n", argv[0]); exit (1);
CMPUT 379 (E.S. Elmallah)
// we may also want to perform STREAM I/O on the socket if ( (sfpin= fdopen (s, "r")) < 0 ) {
fprintf (stderr, "%s: converting s to FILE* \n", argv[0]); exit (1);
// prepare for nonblocking I/O polling from the socket and the keyboard
timeout= 0;
pfd[0].fd= s ; pfd[1].fd= STDIN_FILENO; pfd[0].events= pfd[1].events= POLLIN; pfd[0].revents= pfd[1].revents= 0;
CMPUT 379 (E.S. Elmallah)
while (1) {
rval= poll (pfd, 2, timeout);
if (pfd[0].revents & POLLIN) { // check socket
if (fgets (buf, 80, sfpin) != NULL) printf("%s", buf);
if (pfd[1].revents & POLLIN) {
fgets (buf, 80, stdin);
write (s, buf, strlen(buf) ); }
printf ("\n"); close(s); return 0; }
// stdin input
CMPUT 379 (E.S. Elmallah)
8. Socket Operations for Servers
Theserverexecutes
o s= socket (AF_INET, SOCK_STREAM, 0)
to obtain a handle s for the address to which subsequent client requests are sent,
o bind() to specify a protocol family, port, and local IP address for the socket,
o listen() to indicate how many connection requests can be queued (e.g., listen (s,5)), and
o accept() to wait for an incoming connection.
CMPUT 379 (E.S. Elmallah)
9. Example: A Simple Concurrent Server
refer to file ’server.c’
note the bound on CPU time
the server listens to a fixed port (MYPORT)
the program uses poll() for nonblocking reads from the managing socket, as well as data sockets (with timeout= 0)
the example also illustrates the use of STREAM I/O functions with sockets
CMPUT 379 (E.S. Elmallah)
#include
#include
#include
#define CPU_LIMIT 15 // secs #define CLIENT_LIMIT 5
#define MYPORT 2222
CMPUT 379 (E.S. Elmallah)
int main (int argc, char *argv[]) {
struct rlimit
struct pollfd struct sockaddr_in FILE
i, N, len, port, rval, timeout, s, fromlen; newsock[CLIENT_LIMIT+1];
buf[MAXBUF]; cpuLimit;
pfd[CLIENT_LIMIT+1]; sin, from;
*sfpin[CLIENT_LIMIT+1];
// set a cpu limit using setrlimit (see the previous client code) … … …
CMPUT 379 (E.S. Elmallah)
// create a managing socket
if ( (s= socket (AF_INET, SOCK_STREAM, 0)) < 0 ) { fprintf (stderr, "%s: socket \n", argv[0]);
// bind the managing socket to a name
sin.sin_family= AF_INET; sin.sin_addr.s_addr= htonl (INADDR_ANY); sin.sin_port= htons (MYPORT);
if ( bind (s, (struct sockaddr *) &sin, sizeof sin) < 0) { fprintf (stderr, "%s: bind \n", argv[0]);
CMPUT 379 (E.S. Elmallah)
// indicate how many connection requests can be queued
listen (s, 5);
// prepare for nonblocking I/O polling from the master socket
timeout= 0; pfd[0].fd= s; pfd[0].events= POLLIN; pfd[0].revents= 0;
CMPUT 379 (E.S. Elmallah)
N= 1; // initially, just one descriptor to poll while (1) {
rval= poll (pfd, N, timeout);
if ( (N < CLIENT_LIMIT) && (pfd[0].revents & POLLIN)) {
// accept a new connection
fromlen= sizeof (from);
newsock[N]= accept (s, (struct sockaddr *) &from, &fromlen);
// we may also want to perform STREAM I/O
if ( (sfpin[N]= fdopen ( newsock[N], "r” )) < 0) {
fprintf (stderr, "%s: fdopen \n", argv[0]);
exit (1); }
pfd[N].fd= newsock[N]; pfd[N].events= POLLIN; pfd[N].revents= 0;
} // end if
CMPUT 379 (E.S. Elmallah)
for (i= 1; i < N; i++) {
if (pfd[i].revents & POLLIN) { // check data socket
if ( fgets (buf, MAXBUF, sfpin[i]) != NULL) printf("%s", buf); }
} // end while
for (i= 1; i < N; i++) close (newsock[i]); close (s);
CMPUT 379 (E.S. Elmallah)
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com