04 - socket programming
TRANSCRIPT
-
8/4/2019 04 - Socket Programming
1/12
CS4233 Network Programming
Socket Programming
Chen-Lung Chan
Department of Computer Science
National Tsing Hua University
Socket Interface
UNIX domain socket Local IPC AF_UNIX
Filesystem: path name
Internet domain socket
Internet communications AF_INET
Internet address: IP + Port
A Client-Server Exchange
Clientprocess
Serverprocess
1. Client sends request
2. Server
handlesrequest
3. Server sends response4. Client
handlesresponse
Resource
A serverprocess and one or more clientprocesses
Server manages some resource. Server provides serviceby manipulating
resource for clients.
Network Applications
OS
NetworkInterface
ClientAppl.
SocketOS +NetworkAPIs
OS
NetworkInterface
ServerAppl.
SocketOS +NetworkAPIs
Internet
Client MachineClient Machine Server MachineServer Machine
Access to Network via Program Interface Sockets make network I/O look like files Call system functions to control and communicate Network code handles issues of routing, segmentation.
-
8/4/2019 04 - Socket Programming
2/12
Internet Connections (TCP/IP)
Connection socket pair(140.114.78.11:3479, 140.114.78.20:80)
Server(port 80)
Client
Client socket address140.114.78.11:3479
Server socket address140.114.78.20:80
Client host address140.114.78.11
Server host address140.114.78.20
Note:3479is an portrandomlyallocatedby the kernel
Note:80is awell-knownportassociated with Web servers
Two common paradigms for clients and servers communication Datagrams (UDP protocol, SOCK_DGRAM)
Connections (TCP protocol, SOCK_STREAM)
Connections are point-to-point, full-duplex (2-waycommunication), and reliable. (TODAYS TOPIC!)
Clients
Examples of client programs
Web browsers, ftp, telnet, ssh How does a client find the server?
The IP address in the server socket address identifies thehost (more precisely, an adaptor on the host)
The (well-known) port in the server socket address identifiesthe service, and thus implicitly identifies the server processthat performs that service.
Examples of well known ports Port 7: Echo server
Port 23: Telnet server Port 25: Mail server
Port 80: Web server
Using Ports to Identify Services
Web server(port 80)
Client host
Server host 140.114.78.20
Echo server(port 7)
Service request for140.114.78.20:80
(i.e., the Web server)
KernelClient
Web server(port 80)
Echo server(port 7)
Service request for140.114.78.20:7
(i.e., the echo server)KernelClient
Servers
See /etc/services for a
comprehensive list of theservices available on aLinux machine.
Servers are long-running processes (daemons). Created at boot-time (typically) by the init process (process 1)
Run continuously until the machine is turned off.
Each server waits for requests to arrive on a well-known port associated with a particular service. Port 7: echo server
Port 23: telnet server
Port 25: mail server
Port 80: HTTP server
A machine that runs a server process is also often
referred to as a server.
-
8/4/2019 04 - Socket Programming
3/12
Using netstat
The netstatcommand prints a lot of
useful network information such asnetwork connections, routing tables, andinterface statistics. netstat: display a list of open sockets
netstata: show both listening and non-listening sockets
Using netstatto view the status of yoursocket program!
Sockets
What is a socket?
To the kernel, a socket is an endpoint ofcommunication. To an application, a socket is a file descriptor that
lets the application read/write from/to the network. Remember: All Unix I/O devices, including networks, are
modeled as files.
Clients and servers communicate with each byreading from and writing to socket descriptors.
The main distinction between regular file I/Oand socket I/O is how the application opensthe socket descriptors.
Overview of the SocketsInterface
Client /ServerSession
Client Server
socket socket
bind
listen
read
writeread
write
Connectionrequest
read
close
close EOF
Await connectionrequest fromnext client
open_listenfd
open_clientfd
acceptconnect
struct sockaddr_in serveraddr;
/* fill in serveraddr with an address */
/* Connect takes (struct sockaddr *) as its second argument */
connect(clientfd, (struct sockaddr *) &serveraddr,sizeof(serveraddr));
Network Byte Ordering Network is big-endian, host may be big- or little-endian Functions work on 16-bit (short) and 32-bit (long) values htons()/htonl(): convert host byte order to network byte order ntohs()/ntohl(): convert network byte order to host byte order Use these to convert network addresses, ports,
Structure Casts You will see a lot of structure casts
Socket Programming Cliches
-
8/4/2019 04 - Socket Programming
4/12
-
8/4/2019 04 - Socket Programming
5/12
Echo Client: socket()
int clientfd; /* socket descriptor */
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1; /* check errno for cause of error */
... (more)
socket() creates a socket descriptor on the
client. AF_INET: indicates that the socket is associated
with Internet protocols. SOCK_STREAM: selects a reliable byte stream
connection.
Echo Client: gethostbyname()
The client then builds the servers Internet address.
int clientfd; /* socket descriptor */
struct hostent *hp; /* DNS host entry */
struct sockaddr_in serveraddr; /* servers IP address */
...
/* fill in the server's IP address and port */
if ((hp = gethostbyname(hostname)) == NULL)
return -2; /* check h_errno for cause of error */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr,(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
serveraddr.sin_port = htons(port);
Echo Client: connect()
Finally, the client creates a connection with the server. Client process suspends (blocks) until the connection is
created.
After resuming, the client is ready to begin exchangingmessages with the server via Unix I/O calls on descriptorsockfd.
int clientfd; /* socket descriptor */
struct sockaddr_in serveraddr; /* server address */
...
/* Establish a connection with the server */
if (connect(clientfd, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) < 0)
return -1;
Echo Client: read() & write()
After the connection is established, we canuse read() and write() to exchange data
between the client and the server. The use of read() and write() are the same as we
mentioned in Direct File I/O.
However, recv() and send() are suggested dueto their compatibility with Winsock. #include
ssize_t recv(int s, void *buf, size_t len, int flags)
ssize_t send(int s, const void *buf, size_t len, intflags)
-
8/4/2019 04 - Socket Programming
6/12
Servers and Sockets
client 1 server client 2
call connect call accept
ret connectret accept
call connect
call readwrite
ret readclose
close call accept
ret connect
call read
ret read
close
write
ret accept
close
Server must be able to handle multiple requests
Where should pending connections be queued up?
Echo Server (1/2)
Create a socket
socket() Announce the service
bind()
Wait for connection listen()
accept()
Exchange data read(), write()
recv(), send() Close the socket
close()
Echo Server (2/2)
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
return -1;
/* Listenfd will be an endpoint for all requests to porton any IP address for this host */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) < 0)
return -1;
/* Make it a listening socket ready to accept connection requests */
if (listen(listenfd, LISTENQ) < 0)
return -1;
Echo Server: Initialize SocketAddress
struct sockaddr_in serveraddr; /* server's socket addr */
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
IP addresses INADDR_ANY: address to accept any incoming messages INADDR_LOOPBACK: 127.0.0.1 (local host) The server is only active on the specified IP address
Ex: public IP: 140.114.78.20, but the program bind at 127.0.0.1
only the clients in the local host can contact the server
IP addr and port stored in network (big-endian) byte order
htonl() converts longs from host byte order to network byte order. htons() converts shorts from host byte order to network byte order.
-
8/4/2019 04 - Socket Programming
7/12
Echo Server: bind() & listen()
bind() associates the socket with the socket addresswe just created.
listen() indicates that this socket will accept connection(connect()) requests from clients.
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, (struct sockaddr *)&serveraddr,
sizeof(serveraddr)) < 0)
return -1;if (listen(listenfd, LISTENQ) < 0)
return -1;
Echo Server: accept()
listenfd(3)
Client
1. Server blocks in accept(),
waiting for connection requeston listening descriptor listenfd.clientfd
Server
listenfd(3)
Client
clientfd
Server2. Client makes connectionrequest by calling and blockingin connect().
Connectionrequest
listenfd(3)
Client
clientfd
Server
3. Server returns connfd from
accept(). Client returns fromconnect(). Connection is nowestablished between clientfd andconnfd.
connfd(4)
Echo Server: Main Loop
The server loops endlessly, waiting for connectionrequests, then reading input from the client, andechoing the input back to the client.
main() {
/* create and configure the listening socket */
while(1) {
/* accept(): wait for a connection request */
/* echo(): read and echo input lines from client til EOF */
/* close(): close the connection */
}
}
Echo Server: accept()
int listenfd; /* listening descriptor */
int connfd; /* connected descriptor */
struct sockaddr_in clientaddr;int clientlen;
clientlen = sizeof(clientaddr);
connfd = accept(listenfd, (struct sockaddr_in *)&clientaddr,
&clientlen);
accept() blocks waiting for a connection request.
accept() returns a connected descriptor(connfd) with the sameproperties as the listening descriptor(listenfd) Returns when the connection between client and server is created
and ready for I/O transfers. All I/O with the client will be done via the connected socket.
accept() also fills in clients IP address.
-
8/4/2019 04 - Socket Programming
8/12
Summary of Socket APIs
int socket(int domain, int type, int protocol);
int connect(int sockfd, const struct sockaddr *serv_addr, socklen_t
addrlen); int bind(int sockfd, struct sockaddr *my_addr, socklen_t addrlen);
int listen(int s, int backlog);
int accept(int s, struct sockaddr *addr, socklen_t *addrlen);
ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
ssize_t recv(int s, void *buf, size_t len, int flags);
ssize_t send(int s, const void *buf, size_t len, int flags); int shutdown(int s, int how);
int close(int fd);
uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort);
Other Socket APIs - Address
Internet address manipulation struct hostent *gethostbyname(const char *name)
returns a structure of type hostentfor the given host name in_addr_t inet_addr(const char *cp)
convert the Internet host address cp from numbers-and-dots notationinto binary data in network byte order
char *inet_ntoa(struct in_addr in) convert the Internet host address in given in network byte order to a
string in standard numbers-and-dots notation (a.b.c.d) The string is returned in a statically allocated buffer, which subsequent
calls will overwrite.
Socket name int getsockname(int s, struct sockaddr *name, socklen_t *namelen)
get socket name int getpeername(int s, struct sockaddr *name, socklen_t *namelen)
get name of connected peer socket
Other Socket APIs - Socket Options
int setsockopt(SOCKET s, int level, intoptname, const char FAR* optval, int optlen)
int getsockopt(SOCKET s, int level, intoptname, char FAR* optval, int FAR* optlen)
Useful options level = SOL_SOCKET
SO_RCVBUF
SO_SNDBUF
level = IPPROTO_TCP
TCP_NODELAY
Some Helpful Tools
ps The pscommand reports process status program.
telnet The telnetcommand can be used as a client
program for testing. Ex: telnet cs22.cs.nthu.edu.tw 21
Then, we can communicate directly with the FTP server.
netstat The netstatcommand prints a lot of useful network
information such as network connections, routingtables, and interface statistics. Ex: we can see the actual address that our program binds.
-
8/4/2019 04 - Socket Programming
9/12
Problem: Close Socket
int sock = socket(AF_INET, SOCK_STREAM, 0);bind(sock, (struct sockaddr *)&name, sizeof(struct sockaddr_in));
listen(sock, 5);int ns = accept(sock, NULL, NULL);char buf[1024] = "Test!!\r\n";send(ns, buf, strlen(buf), 0);close(ns);close(sock);
When you re-execute the above code, you may get an error ofBind: Address Already in Use .
This is because the socket is not released immediately. $ netstat -a
cs22.4233 cs22.50414 5840 0 10136 0 TIME_WAIT
Bind: Address Already in Use (1/2)
LAST_ACK
Local end initiates closure Remote end initiates closure
Closing first guaranteesTIME_WAIT
States of a server socket
receive ACK
close() is called,send FIN
Closing second avoidsTIME_WAIT
CLOSED
TIME_WAIT
FIN_WAIT_2 CLOSING
FIN_WAIT_1
close() is called,send FIN
receive ACK receive FINand send ACK
receive FINand send ACK
receive ACK
timeout completes
CLOSE_WAIT
ESTABLISHED
receive FINand send ACK
Bind: Address Already in Use (2/2)
It is possible for the process to completebefore the kernel has released the associatednetwork resource, and this port cannot bebound to another process until the kernel hasdecided that it is done.
Avoidance SO_REUSEADDR
Use setsockopt() to set the SO_REUSEADDR socketoption, which explicitly allows a process to bind to a portwhich remains in TIME_WAIT
Client closes first
Reduce timeout Shorten the timeout associated with TIME_WAIT
Design a Protocol (1/2)
Avoid passing binary data 32 bit vs 64 bit
Byte order Little endian vs big endian
Ex: FTP telnet cs22.cs.nthu.edu.tw 21
220-
220-=====================================================
220- Department of Computer Science
220- National Tsing Hua University
220-
220- Host: cs22.cs.nthu.edu.tw [140.114.87.72]
220------------------------------------------------------
220- Connected from: vc.cs.nthu.edu.tw [140.114.78.20]
220 cs22 FTP server (Version 4.122 Fri Feb 5 17:14:49 CST 1999) ready.
-
8/4/2019 04 - Socket Programming
10/12
Design a Protocol (2/2)
Ex: FTP contd
HELP
214- The following commands are recognized (* =>'s unimplemented).
USER PORT STOR MSAM* RNTO NLST MKD CDUP
PASS PASV APPE MRSQ* ABOR SITE XMKD XCUP
ACCT* TYPE MLFL* MRCP* DELE SYST RMD STOU
SMNT* STRU MAIL* ALLO CWD STAT XRMD SIZE
REIN* MODE MSND* REST* XCWD HELP PWD MDTM
QUIT RETR MSOM* RNFR LIST NOOP XPWD
USER xxxxxxxx
331 Password required for xxxxxxxx.
commands
return code
FTP Protocol
Client Server
accept()
connect()
220 Welcome Message
USER xxxx
331 Password required for xxxx.
PORT a,b,c,d,e,f
200 PORT command successful.
RETR filename
bind() & listen() connect()
accept()
bind() & listen()
QUIT
Hint: CRLF = \r\nPASS yyyy
230 User xxxx logged in.
Notes of TCP Socket (1/3)
The result of recv() on a TCP socket may notbe the same as your prediction.
Ex1: A sends This is a test!!\r\n to B In A: send(sA, This is a test!!\r\n, 18, 0);
In B: recv(sB, buf, sizeof(buf), 0);
What is the result of buf? It may be
This is a test!!\r\n
This is a
This
Notes of TCP Socket (2/3)
Ex2: A sends This is a test!!\r\n and Testagain!!\r\n to B
In A: send(sA, This is a test!!\r\n, 18, 0);send(sA, Test again!!\r\n, 14, 0);
In B: recv(sB, buf, sizeof(buf), 0);
What is the result of buf? It may be
This is a test!!\r\n
This is a test!!\r\nTest again!!\r\n
This is a
This is a test!!\r\nTest
-
8/4/2019 04 - Socket Programming
11/12
Notes of TCP Socket (3/3)
The return value of recv(), i.e., the length,
is unpredictable. Ensure that the message has been
completely received before parsing it.
What should we do?
Append the received data into a buffer Repeat the above step until \r\n is received
Parsing the Message (1/2)
String operations strcmp() strtok() strstr() sprintf()
The above functions only deal with strings, i.e., acharacter array which ends with \0. Ex: char buf[5] = test;
buf[0] = t; buf[1] = e; buf[2] = s; buf[3] = t; buf[4] = \0;
So, if you receive 10 bytes from the socket and storethem into char buf[20], remember to set buf[10] as\0 before you use the above string functions. Hint: always let the content of the buffer be a string
Parsing the Message (2/2)
char buf[256]
256
int count = recv(sock, buf, sizeof(buf), 0);T e s
T e s \0
buf[count] = \0;
char *p = strstr(buf, \r\n);
t \r \n T int len = recv(sock, buf+count, sizeof(buf)-count, 0);
t \r \n T
buf[count+len] = \0;
\0
p = strstr(buf, \r\n);
// get the message from the buffer
memcpy();
Stabilize Your Program
Message parsing Be careful to use string operations
Check return values The socket APIs would return errors bind(), accept(), connect(), recv(), send()
Remember to release unnecessary resources Close the sockets once you do not require them
anymore
Thread synchronization/interprocesscommunications Be careful to design the system flow.
-
8/4/2019 04 - Socket Programming
12/12
What is Peer-to-Peer (P2P)?
Peer-to-peer is a way of structuring
distributed applications such that theindividual nodes have symmetric roles.
Rather than being divided into clientsand servers each with quite distinct roles,in P2P applications a node may act as
both a client and a server.
Client-Server vs. P2P
Client-server
Clients are dumb little is assumed Servers do most things (compute, store, control)
Centralization makes things simple
But introduces
Single point of failure/bottleneck, tighter control,
P2P
Peers (typically) have equal functionality A peer can be a client, a server, or a router