Network IPC: SocketsChapter 16
Carnegie Mellon
2Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
A Client-Server Transaction
Most network applications are based on the client-server model: A server process and one or more client processes Server manages some resource Server provides service by manipulating resource for
clients Server activated by request from client (vending machine
analogy)
Clientprocess
Serverprocess
1. Client sends request
3. Server sends response4. Client handles
response
2. Server handlesrequest
Resource
Note: clients and servers are processes running on hosts (can be the same or different hosts)
Carnegie Mellon
3Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Computer Networks A network is a hierarchical system of boxes
and wires organized by geographical proximity SAN (System Area Network) spans cluster or machine room
Switched Ethernet, Quadrics QSW, … LAN (Local Area Network) spans a building or campus
Ethernet is most prominent example WAN (Wide Area Network) spans country or world
Typically high-speed point-to-point phone lines
An internetwork (internet) is an interconnected set of networks The Global IP Internet (uppercase “I”) is the most famous
example of an internet (lowercase “i”)
Let’s see how an internet is built from the ground up
Carnegie Mellon
4Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Lowest Level: Ethernet Segment
Ethernet segment consists of a collection of hosts connected by wires (twisted pairs) to a hub
Spans room or floor in a building Operation
Each Ethernet adapter has a unique 48-bit address (MAC address) E.g., 00:16:ea:e3:54:e6
Hosts send bits to any other host in chunks called frames Hub slavishly copies each bit from each port to every other port
Every host sees every bit Note: Hubs are on their way out. Bridges (switches, routers) became cheap
enough to replace them
host host host
hub100 Mb/s100 Mb/s
port
Carnegie Mellon
5Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Next Level: Bridged Ethernet Segment
Spans building or campus
Bridges cleverly learn which hosts are reachable from which ports and then selectively copy frames from port to port
host host host host host
hub hubbridge100 Mb/s 100 Mb/s
host host
hub 100 Mb/s 100 Mb/s
1 Gb/s
host host host
bridge
hosthost
hub
A B
C
X
Y
Carnegie Mellon
6Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Conceptual View of LANs For simplicity, hubs, bridges, and wires are
often shown as a collection of hosts attached to a single wire:
host host host...
Carnegie Mellon
7Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Next Level: internets Multiple incompatible LANs can be
physically connected by specialized computers called routers
The connected networks are called an internet (lower case)
host host host... host host host...
WAN WAN
LAN 1 and LAN 2 might be completely different, totally incompatible
(e.g., Ethernet, Fibre Channel, 802.11*, T1-links, DSL, …)
router router routerLAN 1 LAN 2
Carnegie Mellon
8Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Logical Structure of an internet
Ad hoc interconnection of networks No particular topology Vastly different router & link capacities
Send packets from source to destination by hopping through networks Router forms bridge from one network to another Different packets may take different routes
router
router
routerrouter
router
router
hosthost
Carnegie Mellon
9Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
The Notion of an internet Protocol
How is it possible to send bits across incompatible LANs and WANs?
Solution: protocol software running on each host and router Protocol is a set of rules that governs how hosts and
routers should cooperate when they transfer data from network to network.
Smooths out the differences between the different networks
Carnegie Mellon
10Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
What Does an internet Protocol Do?
Provides a naming scheme An internet protocol defines a uniform format for host
addresses Each host (and router) is assigned at least one of these
internet addresses that uniquely identifies it
Provides a delivery mechanism An internet protocol defines a standard transfer unit
(packet) Packet consists of header and payload
Header: contains info such as packet size, source and destination addresses
Payload: contains data bits sent from source host
Carnegie Mellon
11Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
LAN2
Transferring internet Data Via Encapsulation
protocolsoftware
client
LAN1adapter
Host ALAN1
data(1)
data PH FH1(4)
data PH FH2(6)
data(8)
data PH FH2 (5)
LAN2 frame
protocolsoftware
LAN1adapter
LAN2adapter
Routerdata PH(3) FH1
data PH FH1(2)
internet packet
LAN1 frame
(7) data PH FH2
protocolsoftware
server
LAN2adapter
Host B
PH: Internet packet headerFH: LAN frame header
Carnegie Mellon
12Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Other Issues We are glossing over a number of
important questions: What if different networks have different maximum
frame sizes? (segmentation) How do routers know where to forward frames? How are routers informed when the network topology
changes? What if packets get lost?
These (and other) questions are addressed by the area of systems known as computer networking
Carnegie Mellon
13Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Hardware and Software Organization of an Internet Application
TCP/IP
Client
Networkadapter
Global IP Internet
TCP/IP
Server
Networkadapter
Internet client host Internet server host
Sockets interface(system calls)
Hardware interface(interrupts)
User code
Kernel code
Hardwareand firmware
Carnegie Mellon
14Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
A Programmer’s View of the Internet1. Hosts are mapped to a set of 32-bit IP addresses
128.2.203.179
2. The set of IP addresses is mapped to a set of identifiers called Internet domain names
128.2.203.179 is mapped to www.cs.cmu.edu
3. A process on one Internet host can communicate with a process on another Internet host over a connection
Carnegie Mellon
15Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Internet Connections Clients and servers communicate by sending
streams of bytes over connections. Each connection is: Point-to-point: connects a pair of processes. Full-duplex: data can flow in both directions at the same time, Reliable: stream of bytes sent by the source is eventually
received by the destination in the same order it was sent.
A socket is an endpoint of a connection Socket address is an IPaddress:port pair
A port is a 16-bit integer that identifies a process: Ephemeral port: Assigned automatically by client kernel
when client makes a connection request. Well-known port: Associated with some service provided by a
server (e.g., port 80 is associated with Web servers)
16
Socket vs. file
socket vs. file
– file:
● create(), open(), close(), read(), write(), seek()
– socket
● socket()
● bind()
● connect()
● listen() and accept()
● read(), recv(), recvfrom(), recvmsg()
● write(), send(), sendto(), or sendmsg()
● close()
17
Socket vs file: examples
Creating file
– fd = create(…)
Creating socket
– sd = socket(…)
– Then,
– bind(sd,”address”): attach the socket to IP address and port number
pair.
– connect(sd, “address”): connect local socket to remote socket with
address.
18
Typical Client Mechanism
my_sd = socket( )connect( my_sd, <presumed address,port of some server> )send( my_sd, <the stuff you want sent> )recv( my_sd, <where to put what you receive> )close( my_sd )
클라이언트 A
클라이언트 B
클라이언트 C
서버참가자 :클라이언트 A클라이언트 B클라이언트 C
19
Typical Server Mechanism
my_sd = socket( )bind(my_sd, <local address, mainly a port number> )listen(my_sd)start loop his_sd = accept(my_sd,
<to be filled in with his incoming info>) recv(his_sd,<where to put what you receive>) send(his_sd,<the stuff you want sent>) close(his_sd)end loop
클라이언트 서버
ServerSocketSocket
4242
2789
20
Socket program sample I: server
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int main() {
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
21
Socket program sample I: server
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
while(1) {
char ch; printf("server waiting\n");
client_sockfd=accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
}
22
Socket program sample I: client
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/un.h>
#include <unistd.h>
int main() {
int sockfd;
int len;
struct sockaddr_in address;
int result;
23
char ch = 'A';
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family=AF_INET;
address.sin_addr.s_addr = inet_addr("206.83.185.93");
address.sin_port = htons(9734);
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
if (result == 1) {
perror("oops: client1");
exit(1);
}
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
printf("char from server = %c\n", ch);
close(sockfd);
exit(0);
}
24
Connection-Oriented vs. Connectionless
Connectionless protocol (Datagram interface)
– A datagram is a self-contained message.
– analogous to mailing someone a letter.
– No logical connection between peers
– Subject to out-of-order delivery and loss
– UDP (User Datagram Protocol)
Connection-oriented protocol (Stream interface)
– Like making a phone call.
– A point-to-point virtual connection between both ends of the call
– TCP (Transmission Control Protocol)
25
Socket System Callsfor Connection-Oriented Protocol
socket()
bind()
listen()
accept()
socket()
connect()
write()
write()
read()
read()
Server(connection-oriented protocol)
blocks until connectionfrom client
process request
connection establishment
data(request)
data(reply)
Client
26
Socket System Callsfor Connectionless Protocol
socket()
bind()
recvfrom()
socket()
bind()
sendto()
sendto()recvfrom()
Server(connectionless protocol)
blocks until datareceived from a client
process request
data(request)
data(reply)
Client
27
Interesting articles
● http://stackoverflow.com/questions/13021796/simultaneously-read-
and-write-on-the-same-socket-in-c-or-c
28
Socket Descriptors
Domain: AF_INET, AF_INET6, AF_UNIX, AF_UNSPEC
Types: SOCK_DGRAM, SOCK_RAW, SOCK_SEQPACKET, SOCK_STREAM
Protocol: 0 to indicate the default protocol for the given domain and socket type
– TCP for AF_INET and SOCK_STREAM
– UDP for AF_INET and SOCK_DGRAM
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
Returns: file (socket) descriptor if OK, –1 on error
29
Socket communication domains and types
Domain Description
AF_INETAF_INET6AF_UNIXAF_UNSPEC
IPv4 Internet domainIPv6 Internet domainUNIX domainunspecified
Type Description
SOCK_DGRAMSOCK_RAWSOCK_SEQPACKET
SOCK_STREAM
fixed-length, connectionless, unreliable messagesdatagram interface to IP (optional in POSIX.1)fixed-length, sequenced, reliable, connection-ori-ented messagessequenced, reliable, bidirectional, connection-ori-ented byte streams
Carnegie Mellon
30Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
(1) IP Addresses 32-bit IP addresses are stored in an IP
address struct IP addresses are always stored in memory in network
byte order (big-endian byte order)
True in general for any integer transferred in a packet header from one machine to another.
E.g., the port number used to identify an Internet connection.
/* Internet address structure */struct in_addr { uint32_t s_addr; /* network byte order (big-endian) */};
31
Byte Ordering
Endianness: order of bytes within 16, 32, and 64 bit integer
The TCP/IP: Big Endian vs. Intel processors: Little Endian
Host to network or network to host
32
Byte Ordering
#include <arpa/inet.h>uint32_t htonl(uint32_t hostint32);uint16_t htons(uint16_t hostint16);uint32_t ntohl(uint32_t netint32);uint16_t ntohs(uint16_t netint16);
Useful network byte-order conversion functions (“l” = 32 bits, “s” = 16 bits)
htonl: convert uint32_t from host to network byte orderhtons: convert uint16_t from host to network byte orderntohl: convert uint32_t from network to host byte orderntohs: convert uint16_t from network to host byte order
33
Socket Descriptors
Communication on a socket is bidirectional. We can disable I/O on a
socket with the shutdown function.
#include <sys/socket.h>
int shutdown (int sockfd, int how);
Returns: 0 if OK, –1 on error
34
Address structure
Internet address defined in <netinet/in.h>
struct in_addr {in_addr_t s_addr; /* IPv4 address */
};
struct sockaddr_in {sa_family_t sin_family; /* address family */in_port_t sin_port; /* port number */struct in_addr sin_addr; /* IPv4 address */
};
// example
address.sin_family=AF_INET;
address.sin_addr.s_addr =
inet_addr("206.83.185.93");
address.sin_port = htons(9734);
35
Address Structure
Conversion between the binary address format and the dotted-decimal notation
Only AF_INET and AF_INET6 domains supported
inet_pton: dotted decimal string → IP address in network byte order
inet_ntop: IP address in network byte order → dotted decimal string
#include <arpa/inet.h>const char *inet_ntop(int domain, const void *addr, char *str, socklen_t size);int inet_pton(int domain, const char *str, void *addr);
“n” denotes network “p” denotes presentation
IP address: 0x8002C2F2 = 128.2.194.242
// example// IPv4 demo of inet_ntop() and inet_pton()struct sockaddr_in sa;char str[INET_ADDRSTRLEN];// store this IP address in sa:inet_pton(AF_INET, "192.0.2.33", &(sa.sin_addr));// now get it back and print itinet_ntop(AF_INET, &(sa.sin_addr), str, INET_ADDRSTRLEN);printf("%s\n", str); // prints "192.0.2.33"
36
Bind(): Associating Addresses with Sockets
To associate an address with a socket, to discover the address bound to a
socket, and to find out the peer’s address
For a client’s socket, we can let the system choose a default address for us,
whereas a well-known address should be associated with the server’s socket.
The system will choose an address and bind it to our socket, if we call con-
nect or listen without first binding an address to the socket.
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr,
socklen_t len);
Returns : 0 if OK, -1 on error
37
Connection Establishment
The backlog argument provides a hint to the system of the number of
outstanding connect requests that it should enqueue on behalf of the
process.
#include <sys/socket.h>
int listen(int sockfd, int backlog);
Returns : 0 if OK, -1 on error
38
Socket program sample I: server(again)int main() {
int server_sockfd, client_sockfd;
int server_len, client_len;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
server_address.sin_family = AF_INET;
server_address.sin_addr.s_addr = htonl(INADDR_ANY);
server_address.sin_port = htons(9734);
server_len = sizeof(server_address);
bind(server_sockfd,
(struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
…
}
39
Connection Establishment
It creates a connection to the specified server, addr. If sockfd is not bound to
an address, a default address will be bound to the caller.
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,
socklen_t len);
Returns : 0 if OK, -1 on error
40
Socket program sample I: client(again)
…
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family=AF_INET;
address.sin_addr.s_addr = inet_addr("206.83.185.93");
address.sin_port = htons(9734);
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *)&address, len);
if (result == -1) {
perror("oops: client1");
exit(1);
}
write(sockfd, &ch, 1);
read(sockfd, &ch, 1);
…
41
What if connect() fails?: Exponential Backoff(Figure 16.9)
#include "apue.h"#include <sys/socket.h>
#define MAXSLEEP 128
int connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen) {
int nsec;
/* Try to connect with exponential backoff. */for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
if (connect(sockfd, addr, alen) == 0) {/* Connection accepted. */return(0);
}
/* Delay before trying again. */if (nsec <= MAXSLEEP/2)
sleep(nsec);}return(-1);
}
42
Connection Establishment
The file descriptor returned is a socket descriptor that is connected to the client that
called connect. This new socket descriptor has the same socket type and address
family as sockfd.
The original socket passed to accept is not associated with the connection, but in-
stead remains available to receive additional connect requests.
On return, accept will fill in the client’s address in addr.
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *restrict addr,
socklen_t *restrict len);
Returns : file(socket) descriptor if OK, -1 on error
43
Socket program sample I: server
bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
listen(server_sockfd, 5);
while(1) {
char ch; printf("server waiting\n");
client_sockfd=accept(server_sockfd,
(struct sockaddr *)&client_address, &client_len);
read(client_sockfd, &ch, 1);
ch++;
write(client_sockfd, &ch, 1);
close(client_sockfd);
}
}
44
Connection Establishment : Figure 16.10
#include "apue.h"#include <errno.h>#include <sys/socket.h>
int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen){{
int fd; int err = 0;
if ((fd = socket(addr->sa_family, type, 0)) < 0)return(-1);
if (bind(fd, addr, alen) < 0) {err = errno;goto errout;
}if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
if (listen(fd, qlen) < 0) {err = errno;goto errout;
}}return(fd);
errout:close(fd); errno = err; return(-1);
}
45
Data Transfer
read/write can be used to communicate with a socket.
With a connection-oriented socket, the destination address is ignored, as the
destination is implied by the connection. (With a connectionless socket, we
can’t use send unless the destination address is first set by calling connect.)
#include <sys/socket.h>ssize_t sendto(int sockfd, const void *buf, size_t nbytes, int flags, const struct sockaddr *destaddr, socklen_t destlen);
#include <sys/socket.h>ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
Returns : number of bytes sent if OK, -1 on error
Returns : number of bytes sent if OK, -1 on error
46
Data Transfer
We have one more choice when transmitting data over a socket. We
can call sendmsg with a msghdr structure to specify multiple buffers
from which to transmit data, similar to the writev function
#include <sys/socket.h>ssize_t sendmsg (int sockfd, const struct msghdr *msg, int flags);
Returns : number of bytes sent if OK, -1 on error
47
Data Transfer
POSIX.1 defines the msghdr structure to have at least the following
members:
struct msghdr {void *msg_name; /* optional address */socklen_t msg_namelen; /* address size in bytes */struct iovec *msg_iov; /* array of I/O buffers */int msg_iovlen;/*number of elements in array */void *msg_control; /*ancillary data */socklen_t msg_controllen; /*number of ancillary bytes */int msg_flags; /*flags for received message */
.
.
.};
48
Data Transfer
The recv function is similar to read, but allows us to specify some op-
tions to control how we receive the data.
#include <sys/socket.h>ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);
#include <sys/socket.h>ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen);
Returns : length of message in bytes,0 if no messages are available and peer has done an orderly shutdown,
or -1 on error
#include <sys/socket.h>ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
Returns : length of message in bytes,0 if no messages are available and peer has done an orderly shutdown,
or -1 on error
49
Adress lookup
클라이언트 서버
ServerSocketSocket
4242
2789
IP: 192.168.0.2
Port:
So far, we connected to a server with a known IP and a port number
How many connections are possible? - Client side: maximum ports
- Server side: almost unlimited
14344
50
Adress lookup
클라이언트 서버
ServerSocketSocket
● http
2789
www.gmarket.co.kr
Service: http
http://www.gmarket.co.kr ?
14344
Carnegie Mellon
51Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
(2) Internet Domain Names
.net .edu .gov .com
cmu berkeleymit
cs ece
whaleshark128.2.210.175
ics
unnamed root
pdl
www128.2.131.66
amazon
www176.32.98.166
First-level domain names
Second-level domain names
Third-level domain names
Carnegie Mellon
52Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Domain Naming System (DNS)
The Internet maintains a mapping between IP addresses and domain names in a huge worldwide distributed database called DNS
Conceptually, programmers can view the DNS database as a collection of millions of host entries. Each host entry defines the mapping between a set of
domain names and IP addresses. In a mathematical sense, a host entry is an equivalence class
of domain names and IP addresses.
Carnegie Mellon
53Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Properties of DNS Mappings Can explore properties of DNS mappings using
nslookup
Output edited for brevity
Each host has a locally defined domain name localhost which always maps to the loopback address 127.0.0.1
Use hostname to determine real domain name of local host:
linux> nslookup localhostAddress: 127.0.0.1
linux> hostnamewhaleshark.ics.cs.cmu.edu
Carnegie Mellon
54Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Properties of DNS Mappings (cont)
Simple case: one-to-one mapping between domain name and IP address:
Multiple domain names mapped to the same IP address:
linux> nslookup whaleshark.ics.cs.cmu.eduAddress: 128.2.210.175
linux> nslookup cs.mit.eduAddress: 18.62.1.6linux> nslookup eecs.mit.eduAddress: 18.62.1.6
Carnegie Mellon
55Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Properties of DNS Mappings (cont)
Multiple domain names mapped to multiple IP addresses:
Some valid domain names don’t map to any IP address:
linux> nslookup www.twitter.comAddress: 199.16.156.6Address: 199.16.156.70Address: 199.16.156.102Address: 199.16.156.230
linux> nslookup twitter.comAddress: 199.16.156.102Address: 199.16.156.230Address: 199.16.156.6Address: 199.16.156.70
linux> nslookup ics.cs.cmu.edu*** Can't find ics.cs.cmu.edu: No answer
56
Adress lookup
클라이언트 서버
ServerSocketSocket
4242
2789
www.gmarket.co.kr
Service: http
http://www.gmarket.co.kr ?
14344
DNS 서버
IP: 192.168.0.2
IP: 192.168.0.2
Carnegie Mellon
57Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Well-known Ports and Service Names
Popular services have permanently assigned well-known ports and corresponding well-known service names: echo server: 7/echo ssh servers: 22/ssh email server: 25/smtp Web servers: 80/http
Mappings between well-known ports and service names is contained in the file /etc/services on each Linux machine.
Carnegie Mellon
58Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Anatomy of a Connection A connection is uniquely identified by the
socket addresses of its endpoints (socket pair) (cliaddr:cliport, servaddr:servport)
Connection socket pair(128.2.194.242:51213, 208.216.181.15:80)
Server(port 80)
Client
Client socket address128.2.194.242:51213
Server socket address
208.216.181.15:80
Client host address128.2.194.242
Server host address208.216.181.15
51213 is an ephemeral port allocated by the kernel
80 is a well-known portassociated with Web servers
Carnegie Mellon
59Bryant and O’Hallaron, Computer Systems: A Programmer’s Perspective, Third Edition
Using Ports to Identify Services
Web server(port 80)
Client host
Server host 128.2.194.242
Echo server(port 7)
Service request for128.2.194.242:80
(i.e., the Web server)
Web server(port 80)
Echo server(port 7)
Service request for128.2.194.242:7
(i.e., the echo server)
Kernel
Kernel
Client
Client
60
51
Address Lookup (old way - skip)
The hosts known by a given computer system are found by calling
gethostent
#include <netdb.h>
struct hostent *gethostent(void);
void sethostent(int stayopen);
void endhostent(void);
Returns: file (socket) descriptor if OK, –1 on error
52
Address Lookup (old way - skip)
When genhostent returns, we get a pointer to a hostent structure
which might point to a static data buffer that is overwritten each time
we call gethostent.
struct hostent {char *h_name; /* name of host */
char **h_alias; /* pointer to alternate host name array */int h_addrtype; /* address type */int h_length; /* length in bytes of address */char **h_addr_list; /* pointer to array of network addresses */
…}
53
Address Lookup (old way - skip)
We can get network names and numbers with a similar set of inter-
faces.
#include <netdb.h>
struct netent *getnetent(void);struct protoent *getprotoent(void);strcut servent *getservent(void);
void setnetent (int stayopen);void endnetent (void);
All return : pointer if OK, NULL on error
54
Address Lookup (old way - skip)
The netent structure contains at least the following fields
struct netent {char *n_name; /* network name */
char **n_aliases; /* alternate network name array pointer */
int n_addrtype; /* address type */unit32_t n_net; /* network number */
…}
55
Address Lookup (old way - skip)
The network number is returned in network byte order. The address
type is one of the address family constants (AF_INET, for example)
We can map between protocol names and numbers with the following
functions.
#include <netdb.h>
struct protoent *getprotobyname(const char *name);struct protoent *getprotobynumber(int proto);struct protoent *getprotoent(void);
void setprotoent (int stayopen);void endprotoent (void);
All return : pointer if OK, NULL on error
56
Address Lookup (old way - skip)
The protoent structure as defined by POSIX.1 has at least the follow-
ing members:
struct protoent {char *p_name; /* protocol name */
char **p_aliases; /* pointer to alternate protocol name array*/int p_proto; /* protocol number */
…}
57
Address Lookup (old way - skip)
Services are represented by the port number portion of the address.
Each service is offered on a unique, well-known port number. We can
map a service name to a port number with getservbyname, map a
port number to a service name with getservbyport, or scan the ser-
vices database sequentially with getservent.
#include <netdb.h>
struct servent *getservbyname (const char *name, const char *proto);struct servent *getservbynumber (int port, const char *proto);struct servent *getservent (void);
void setservent (int stayopen);void endservent (void);
All return : pointer if OK, NULL on error
58
Address Lookup (old way - skip)
The servent is defined to have at least the following members:
struct servent {char *s_name; /* service name */
char **s_aliases; /* pointer to alternate service name array*/int s_proto; /* port number */
char *s_proto; /* name of protocol */…}
59
Address Lookup
Posix.1 defines several new functions to allow an application to map from
a host name and a service name to an address and vice versa. These
functions replace the older gethostbyname and gethostbyaddr func-
tions.
The getaddrinfo function allows us to map a host name and a service
name to an address.
#include <sys/socket.h>#include <netdb.h>
int getaddrinfo (const char *restrict host, const char *restrict service, const struct addrinfo *restrict hint, struct addrinfo **restrict res);
void freeaddrinfo (struct addrinfo *ai);
Returns : 0 if OK, nonzero error code on error
60
Address Lookup
The addrinfo structure is defined to include at least the following
members:members:
struct addrinfo {int ai_flags; /* customize behavior */int ai_falmily; /* address family */int ai_socktype; /* socket type */int ai_protocol; /* protocol */socklen_t ai_addrlen; /* length in bytes of address */struct sockaddr *ai_addr;/* address */char *ai_canonname; /* canonical name of host */struct *ai_next; /* next in list */
…}
61
Flags for addrinfo structure
We can supply an optional hint to select addresses that meet certain
criteria. The hint is a template used for filtering addresses and uses
only the ai_family, ai_flags, ai_protocol, and
ai_socktype fields.
Flag Description
AI_ADDRCONFIGAI_ALL
AI_CANONNAMEAI_NUMBERICHOSTAI_NUMBERICSERVAI_PASSIVEAI_V4MAPPED
Query for whichever address type (IPv4 or IPv6) is config-ured.
Look for both IPv4 and IPv6 addresses (used only with AI_V4MAPPED).
Request a canonical name (as opposed to an alias).
Return the host address in numeric format.
Return the service as a port number.
Socket address is intended to be bound for listening.
If no IPv6 addresses are found, return IPv4 addresses mapped in IPv6 format.
62
Address Lookup
If getaddrinfo fails, we can’t use perror or strerror to generate an er-
ror message. Instead, we need to call gai_strerror to convert the
error code returned into an error message.
#include <netdb.h>
const char *gai_strerror (int error);
Returns : a pointer to a string describing the error
63
Address Lookup
The getnameinfo function converts an address into a host name and
a service name.
#include <sys/socket.h>#include <netdb.h>
int getnameinfo (const struct sockaddr *restrict addr, socklen_t alen, char *restrict host, socklen_t hostlen, char *restrict service, socklen_t servlen, unsigned int flags);
Returns : 0 if OK, nonzero on error
71
Address Lookup : Figure 16.8
This program illustrates the use of the getaddrinfo function.
$ ./a.out harry nfsflags canon family inet type stream protocol TCP host harry address 192.168.1.105 port 2049flags canon family inet type stream protocol UDP host harry address 192.168.1.105 port 2049
A new service can be registered by editing /etc/services
64
Flags for addrinfo structure
The flags argument gives us some control over how the translation is
done
Flag Description
NI_DGRAMNI_NAMEREQDNI_NOFQDN
NI_NUMBERICHOSTNI_NUMBERICSERV
The service is datagram based instead of stream based.
If the host name can’t be found, treat this as an error.
Return only the node name portion of the fully-qualified domain name for local hosts.
Return the numeric form of the host address instead of the name.
Return the numeric form of the service address (i.i., the port number) instead of the name.
65
Address Lookup : Figure 16.8
#include “apue.h”#include <netdb.h>#include <arpa/inet.h>#if defined(BSD) || defined(MACOS)#include <sys/socket.h>#include <netinet/in.h>#endif
void print_family(struct addrinfo *aip){ printf(" family "); switch (aip->ai_family) { case AF_INET: printf("inet");
break; case AF_INET6: printf("inet6");
break; case AF_UNIX: printf("unix");
break; case AF_UNSPEC: printf("unspecified");
break; default: printf("unknown"); }}
66
Address Lookup : Figure 16.8
void print_type(struct addrinfo *aip){ printf(" type "); switch (aip->ai_socktype) { case SOCK_STREAM: printf("stream");
break; case SOCK_DGRAM: printf("datagram");
break; case SOCK_SEQPACKET: printf("seqpacket");
break; case SOCK_RAW: printf("raw");
break; default: printf("unknown (%d)", aip->ai_socktype); }}
67
Address Lookup : Figure 16.8
void print_protocol(struct addrinfo *aip){ printf(" protocol "); switch (aip->ai_protocol) { case 0: printf("default");
break; case IPPROTO_TCP: printf("TCP");
break; case IPPROTO_UDP: printf("UDP");
break; case IPPROTO_RAW: printf("raw");
break; default:printf("unknown (%d)", aip->ai_protocol); }}
68
Address Lookup : Figure 16.8
void print_flags(struct addrinfo *aip){ printf("flags"); if (aip->ai_flags == 0) { printf(" 0"); } else {
if (aip->ai_flags & AI_PASSIVE) printf(" passive");if (aip->ai_flags & AI_CANONNAME) printf(" canon");if (aip->ai_flags & AI_NUMERICHOST) printf(" numhost");
#if defined(AI_NUMERICSERV)if (aip->ai_flags & AI_NUMERICSERV) printf(" numserv");
#endif#if defined(AI_V4MAPPED)
if (aip->ai_flags & AI_V4MAPPED) printf(" v4mapped");#endif#if defined(AI_ALL)
if (aip->ai_flags & AI_ALL) printf(" all");#endif }}
69
Address Lookup : Figure 16.8
int main(int argc, char *argv[]){ struct addrinfo*ailist, *aip; struct addrinfohint; struct sockaddr_in *sinp; const char *addr; int err; char abuf[INET_ADDRSTRLEN];
if (argc != 3) err_quit("usage: %s nodename service", argv[0]);
hint.ai_flags = AI_CANONNAME; hint.ai_family = 0; hint.ai_socktype = 0; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_canonname = NULL; hint.ai_addr = NULL; hint.ai_next = NULL;
70
Address Lookup : Figure 16.8
if ((err = getaddrinfo(argv[1], argv[2], &hint, &ailist)) != 0)err_quit("getaddrinfo error: %s", gai_strerror(err));
for (aip = ailist; aip != NULL; aip = aip->ai_next) { print_flags(aip); print_family(aip); print_type(aip); print_protocol(aip); printf("\n\thost %s",
aip->ai_canonname?aip-> ai_canonname:"-"); if (aip->ai_family == AF_INET) {
sinp = (struct sockaddr_in *)aip->ai_addr;addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf,
INET_ADDRSTRLEN);printf(" address %s", addr?addr:"unknown");printf(" port %d", ntohs(sinp->sin_port));
} printf("\n");
} exit(0); }
82
Data Transfer
Connection-oriented uptime (registered as a service: ruptime)
– More work and time are needed to establish a connection, and each connec-tion consumes more resources from the O.S.
– Client (Figure 16.14)
– Server (Figure 16.16)
Connectionless uptime
– With a connectionless socket, packets can arrive out of order, and can be lost.
– Client (Figure 16.17)
– Server (Figure 16.18)
83
Data Transfer : Figure 16.14
#include "apue.h"#include <netdb.h>#include <errno.h>#include <sys/socket.h>
#define MAXADDRLEN 256#define BUFLEN 128
extern int connect_retry(int, const struct sockaddr *, socklen_t);
voidprint_uptime(int sockfd){ int n; char buf[BUFLEN];
while ((n = recv(sockfd, buf, BUFLEN, 0)) > 0) write(STDOUT_FILENO, buf, n); if (n < 0)
err_sys("recv error");}
84
Data Transfer : Figure 16.14
int main(int argc, char *argv[]){ struct addrinfo *ailist, *aip; struct addrinfo hint; int sockfd, err;
if (argc != 2) err_quit("usage: ruptime hostname");\
hint.ai_flags = 0; hint.ai_family = 0; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_canonname = NULL; hint.ai_addr = NULL; hint.ai_next = NULL;
if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)err_quit("getaddrinfo error: %s", gai_strerror(err));
85
Data Transfer : Figure 16.14
for (aip = ailist; aip != NULL; aip = aip->ai_next) {if ((sockfd = socket(aip->ai_family,
SOCK_STREAM, 0)) < 0)err = errno;
if (connect_retry(sockfd, aip->ai_addr, aip->ai_addrlen) < 0) {
err = errno; } else {
print_uptime(sockfd);exit(0);
} } fprintf(stderr, "can't connect to %s: %s\n", argv[1], strerror(err)); exit(1);}
86
#define BUFLEN 128#define QLEN 10#ifndef HOST_NAME_MAX#define HOST_NAME_MAX 256#endif
extern int initserver(int, struct sockaddr *, socklen_t, int);voidserve(int sockfd){ int clfd; FILE *fp; char buf[BUFLEN]; for (;;) { clfd = accept(sockfd, NULL, NULL); if (clfd < 0) { syslog(LOG_ERR, "ruptimed: accept error: %s", strerror(errno)); exit(1); } if ((fp = popen("/usr/bin/uptime", "r")) == NULL) { sprintf(buf, "error: %s\n", strerror(errno)); send(clfd, buf, strlen(buf), 0); } else { while (fgets(buf, BUFLEN, fp) != NULL) send(clfd, buf, strlen(buf), 0); pclose(fp); } close(clfd); }}
Data Transfer : Figure 16.15
87
Data Transfer : Figure 16.15int main(int argc, char *argv[]) { struct addrinfo *ailist, *aip; struct addrinfo hint; int sockfd, err, n; char *host;
if (argc != 1) err_quit("usage: ruptimed");#ifdef _SC_HOST_NAME_MAX n = sysconf(_SC_HOST_NAME_MAX); if (n < 0) /* best guess */#endif n = HOST_NAME_MAX; host = malloc(n); if (host == NULL) err_sys("malloc error"); if (gethostname(host, n) < 0) err_sys("gethostname error"); daemonize("ruptimed"); hint.ai_flags = AI_CANONNAME; hint.ai_family = 0; hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = 0; hint.ai_addrlen = 0; hint.ai_canonname = NULL; hint.ai_addr = NULL; hint.ai_next = NULL;
88
Data Transfer : Figure 16.15
if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) { syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s", gai_strerror(err)); exit(1); } for (aip = ailist; aip != NULL; aip = aip->ai_next) { if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr, aip->ai_addrlen, QLEN)) >= 0) { serve(sockfd); exit(0); } } exit(1);}
89
Data Transfer : Figure 16.16
#define QLEN 10#ifndef HOST_NAME_MAX#define HOST_NAME_MAX 256#endifextern int initserver(int, struct sockaddr *, socklen_t, int);
void serve(int sockfd) { int clfd, status; pid_t pid; for (;;) { clfd = accept(sockfd, NULL, NULL); if (clfd < 0) { syslog(LOG_ERR, "ruptimed: accept error: %s", strerror(errno)); exit(1); } if ((pid = fork()) < 0) { syslog(LOG_ERR, "ruptimed: fork error: %s", strerror(errno)); exit(1); } else if (pid == 0) { /* child */
90
Data Transfer : Figure 16.16
/** The parent called daemonize (Figure 13.1), so* STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO* are already open to /dev/null. Thus, the call to* close doesn't need to be protected by checks that* clfd isn't already equal to one of these values.*/ if (dup2(clfd, STDOUT_FILENO) != STDOUT_FILENO || dup2(clfd, STDERR_FILENO) != STDERR_FILENO) { syslog(LOG_ERR, "ruptimed: unexpected error"); exit(1); } close(clfd); execl("/usr/bin/uptime", "uptime", (char *)0); syslog(LOG_ERR, "ruptimed: unexpected return from exec: %s", strerror(errno)); } else { /* parent */ close(clfd); waitpid(pid, &status, 0); } }}
91
Data Transfer : Figure 16.16
int main(int argc, char *argv[]){
struct addrinfo *ailist, *aip; struct addrinfo hint;int sockfd, err, n; char *host;
if (argc != 1) err_quit("usage: ruptimed");#ifdef _SC_HOST_NAME_MAX
n = sysconf(_SC_HOST_NAME_MAX);if (n < 0) /* best guess */
#endifn = HOST_NAME_MAX;
host = malloc(n);if (host == NULL) err_sys("malloc error");if (gethostname(host, n) < 0) err_sys("gethostname error");daemonize("ruptimed");hint.ai_flags = AI_CANONNAME; hint.ai_family = 0;hint.ai_socktype = SOCK_STREAM; hint.ai_protocol = 0;hint.ai_addrlen = 0; hint.ai_canonname = NULL;hint.ai_addr = NULL; hint.ai_next = NULL;if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s“, gai_strerror(err));
exit(1);}
92
Data Transfer : Figure 16.16
for (aip = ailist; aip != NULL; aip = aip->ai_next) {if ((sockfd = initserver(SOCK_STREAM, aip->ai_addr,
aip->ai_addrlen, QLEN)) >= 0) {serve(sockfd);exit(0);
}}exit(1);
}
93
Data Transfer : Figure 16.17
#define BUFLEN 128#define TIMEOUT 20
voidsigalrm(int signo){}
voidprint_uptime(int sockfd, struct addrinfo *aip){
int n;charbuf[BUFLEN];
buf[0] = 0;if (sendto(sockfd, buf, 1, 0, aip->ai_addr, aip->ai_addrlen) < 0)
err_sys("sendto error");alarm(TIMEOUT);if ((n = recvfrom(sockfd, buf, BUFLEN, 0, NULL, NULL)) < 0) {
if (errno != EINTR)alarm(0);
err_sys("recv error");}alarm(0);write(STDOUT_FILENO, buf, n);
}
94
Data Transfer : Figure 16.17int main(int argc, char *argv[]){
struct addrinfo *ailist, *aip; struct addrinfo hint;int sockfd, err; struct sigaction sa;
if (argc != 2) err_quit("usage: ruptime hostname");
sa.sa_handler = sigalrm; sa.sa_flags = 0; sigemptyset(&sa.sa_mask);if (sigaction(SIGALRM, &sa, NULL) < 0)
err_sys("sigaction error");hint.ai_flags = 0; hint.ai_family = 0;hint.ai_socktype = SOCK_DGRAM; hint.ai_protocol = 0;hint.ai_addrlen = 0; hint.ai_canonname = NULL;hint.ai_addr = NULL; hint.ai_next = NULL;if ((err = getaddrinfo(argv[1], "ruptime", &hint, &ailist)) != 0)
err_quit("getaddrinfo error: %s", gai_strerror(err));
for (aip = ailist; aip != NULL; aip = aip->ai_next) {if ((sockfd = socket(aip->ai_family, SOCK_DGRAM, 0)) < 0) {
err = errno;} else {
print_uptime(sockfd, aip);exit(0);
}}
fprintf(stderr, "can't contact %s: %s\n", argv[1], strerror(err));exit(1);
}
95
// BUFLEN = 128, MAXADDRLEN = 256, HOST_NAME_MAX = 256
extern int initserver(int, struct sockaddr *, socklen_t, int);
void serve(int sockfd){
int n;socklen_t alen;FILE*fp;charbuf[BUFLEN]; charabuf[MAXADDRLEN];
for (;;) {alen = MAXADDRLEN;if ((n = recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr *)abuf, &alen)) < 0) {
syslog(LOG_ERR, "ruptimed: recvfrom error: %s", strerror(errno));
exit(1);}if ((fp = popen("/usr/bin/uptime", "r")) == NULL) {
sprintf(buf, "error: %s\n", strerror(errno));sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *)abuf, alen);} else {
if (fgets(buf, BUFLEN, fp) != NULL)sendto(sockfd, buf, strlen(buf), 0,
(struct sockaddr *)abuf, alen);pclose(fp);
}}
}
Data Transfer : Figure 16.18
96
int main(int argc, char *argv[]){
struct addrinfo *ailist, *aip; struct addrinfo hint;int sockfd, err, n; char *host;
if (argc != 1) err_quit("usage: ruptimed");#ifdef _SC_HOST_NAME_MAX
n = sysconf(_SC_HOST_NAME_MAX);if (n < 0) /* best guess */
#endifn = HOST_NAME_MAX;
host = malloc(n);if (host == NULL) err_sys("malloc error");if (gethostname(host, n) < 0) err_sys("gethostname error");daemonize("ruptimed");hint.ai_flags = AI_CANONNAME; hint.ai_family = 0;hint.ai_socktype = SOCK_DGRAM; hint.ai_protocol = 0;hint.ai_addrlen = 0; hint.ai_canonname = NULL;hint.ai_addr = NULL; hint.ai_next = NULL;if ((err = getaddrinfo(host, "ruptime", &hint, &ailist)) != 0) {
syslog(LOG_ERR, "ruptimed: getaddrinfo error: %s“, gai_strerror(err));
exit(1);}for (aip = ailist; aip != NULL; aip = aip->ai_next) {
if ((sockfd = initserver(SOCK_DGRAM, aip->ai_addr, aip->ai_addrlen, 0)) >= 0) {
serve(sockfd);exit(0);
}}exit(1);
}
Data Transfer : Figure 16.18
97
Socket Options
Three kinds of options
– Generic options that work with all socket types
– Options that are managed at the socket level, but depend on the underlying protocols for support
– Protocol-specific options unique to each individual protocol
#include <sys/socket.h>int setsockopt(int sockfd, int level, int option, const void *val, socklen_t len);int getsockopt(int sockfd, int level, int option, void *val, socklen_t *lenp);
Returns : 0 if OK, -1 on error
98
Socket Options : Figure 16.20
int initserver(int type, const struct sockaddr *addr, socklen_t alen, int qlen){
int fd, err; int reuse = 1;
if ((fd = socket(addr->sa_family, type, 0)) < 0)return(-1);
if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(int)) < 0) {err = errno;goto errout;
}if (bind(fd, addr, alen) < 0) {
err = errno;goto errout;
}if (type == SOCK_STREAM || type == SOCK_SEQPACKET) {
if (listen(fd, qlen) < 0) {err = errno;goto errout;
}}return(fd);
errout:close(fd); errno = err; return(-1);
}
99
Socket System Calls and Association Elements
Associations represented by 5-tuple
{protocol, local-addr, local-process, foreign-addr, foreign-process}
Typical system calls for each association element
socket() bind() listen(), accept()
socket() connect()
socket() bind() recvfrom()
socket() bind() sendto()
protocol local-addr, local-process foreign-addr, foreign-process
Connection-oriented server
Connection-oriented client
Connectionless server
Connectionless client
100
Nonblocking and Asynchronous I/O With socket-based asynchronous I/O, we can arrange to be sent the SIGIO
signal when we can read data from a socket or when space becomes available
in a socket's write queue. Enabling asynchronous I/O is a two-step process.
1. Establish socket ownership so signals can be delivered to the proper processes.
2. Inform the socket that we want it to signal us when I/O operations won't block.
We can accomplish the first step in three ways.
1. Use the F_SETOWN command with fcntl.
2. Use the FIOSETOWN command with ioctl.
3. Use the SIOCSPGRP command with ioctl.
To accomplish the second step, we have two choices.
1. Use the F_SETFL command with fcntl and enable the O_ASYNC file flag.
2. Use the FIOASYNC command with ioctl.
101
Nonblocking IO
By setting a socket to non-blocking, you can effectively "poll" the socket for information. If you try to read from a non-blocking socket and there's no data there, it's not allowed to block—it will return -1 and errno will be set to EWOULDBLOCK.
102
Nonblocking IO
For more details, seehttp://beej.us/guide/bgnet/output/html/singlepage/bgnet.html
103
What other ways can handle multiple simultaneous connections?
● IO multiplexing
– 14_advanced_IO.pdf
● Multi-threading