60-256 System Programming: Sockets
Content
COMP 2560 System Programming:
Sockets
Courtesy of Dr. B. Boufama
modified by Dan Wu
School of Computer Science University of Windsor
–
Instructor: Dr. Dan Wu
Sockets
1
Copyright @ 2019, 2020, 2021 all rights reserved
Content
Content
1
2
3
4
5
6
7
Introducing Sockets
Creating endpoints for communication: socket() Socket Address Structures
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets
2
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets I
Sockets are the traditional UNIX IPC mechanism that allows local/distant processes to talk to each other.
IPC using sockets is based on the client/server paradigm.
Note
Socket connections are bidirectional.
Sockets
3
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets I
Unix domain sockets (datagram sockets)
Internet domain sockets (stream sockets)
The first widespread implementation of the sockets API appeared with 4.2BSD in 1983, and this API has been ported to virtually every UNIX implementation, as well as most other operating systems.
Sockets
4
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Although possible, it is difficult and time consuming to use directly the TCP/IP protocol to implement network applications.
⇒The socket interface acts between the user process and
TCP/IP.
Network
Network
Transport
Transport
03
02
01
Data Link
Data Link
Layers Host A Protocols Host B
04 Process Process
Sockets
Sockets
Sockets
5
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario (stream sockets)
In a typical client-server scenario, applications communicate
using sockets as follows:
* Each application creates a socket. A socket is the
“apparatus” that allows communication,
and both applications require one.
* The server binds its socket to a well-known address
(name) so that clients can locate it.
Sockets
6
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
A socket is created using the socket() system call, which
returns a socket file descriptor used to refer to the socket
in subsequent system calls:
fd = socket(domain, type, protocol);
More details on this call later.
Sockets
7
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
The typical scenario can be described in a bit more details as follows.
The server process creates socket whose name is known by client processes, and listens on that socket for requests from clients.
A client process can talk to the server process by
creating an socket then,
requesting it to be connected to the server’s named socket
If successful, one file descriptor is returned to the client and another one to the server. These file descriptors can be used for read and write allowing the server and client to communicate.
Sockets
8
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
socket()
connect()
read/write
close()
Client
socket()
bind()
listen()
accept()
read/write
exchange message
Server
bind address
create end−point
specify queue
wait
Sockets
9
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
Sockets
10
The key socket system calls are the following:
The socket() system call creates a new socket.
The bind() system call binds a socket to an address. Usually, a server employs
this call to bind its socket to a well-known address so that clients can locate
the socket.
The listen() system call allows a stream socket to accept incoming connections
from other sockets.
The accept() system call accepts a connection from a peer application on a listening stream socket, and optionally returns the address of the peer socket.
The connect() system call establishes a connection with another socket.
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
Sockets
11
The operation of stream sockets can be explained by analogy with the telephone system:
The socket() system call, which creates a socket, is the equivalent of installing a telephone. In order for two applications to communicate, each of them must create a socket.
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
Sockets
12
2. Communication via a stream socket is analogous to a telephone call. One application must connect its socket to another application’s socket before communication can take place. Two sockets are connected as follows:
a) One application calls bind() in order to bind the socket to a well-known
address, and then calls listen() to notify the kernel of its willingness to
accept incoming connections. This step is analogous to having a known
telephone number and ensuring that our telephone is turned on so that
people can call us.
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
Sockets
13
b) The other application establishes the connection by calling connect(),
specifying the address of the socket to which the connection is to be
made. This is analogous to dialing someone’s telephone number.
c) The application that called listen() then accepts the connection using
accept(). This is analogous to picking up the telephone when it rings. If
the accept() is performed before the peer application calls connect(),
then the accept() blocks (“waiting by the telephone”).
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Sockets: typical scenario
Sockets
14
3. Once a connection has been established, data can be transmitted in both directions between the applications (analogous to a two-way telephone conversation) until one of them closes the connection using close(). Communication is performed using the conventional read() and write() system calls or via a number of socket specific system calls (such as send() and recv()) that provide additional functionality.
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
The socket() system
call
socket()
Synopsis:
int socket(int domain, int type, int protocol); socket() creates an endpoint for communication and returns a file descriptor referencing the socket. In case of failure, socket() returns -1.
Note
Calling socket() is the first thing a process must do in order to perform any network I/O operation.
Sockets
15
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Socket’s attributes
Three attributes may differentiate between different kinds of sockets:
The domain: AF_INET for internet and AF_UNIX for same machine IPC.
Note that AF stands for Address Family.
The type of communication: SOCK_STREAM, reliable byte stream connection (TCP) and, SOCK_DGRAM, unreliable connectionless (UDP).
The protocol: the low-level protocol used for communication. This parameter is usually set to 0 in system calls, which means “use the correct/default protocol”.
Sockets
16
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Socket’s attributes
Sockets
17
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Socket’s attributes
Every sockets implementation provides at least two types of
sockets: stream and datagram.
These socket types are supported in both the UNIX and the
Internet domains.
Sockets
18
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Example
When a reliable byte-stream connection is requested across the internet:
sd = socket(AF INET, SOCK STREAM, 0);
man socket
man 7 socket
The bind() system call binds a socket to an address.
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
Typically, we bind a server’s socket to a well-known address—that is, a fixed address that is known in advance to client applications that need to communicate with that server.
First, let us talk about address
Sockets
19
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Socket Address Structure
Most socket functions require an argument pointer to a socket address structure, which is protocol dependent.
In particular, we have:
1
2
3
Internet socket address structure, Unix socket address structure,
Generic Socket Address Structure
Sockets
20
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Socket Address Structure
Sockets
21
struct type1 {
int i;
int k;
} ;
struct type2 {
char arr1[2];
char ar2[6]
} ;
struct generic_type {
int i[2];
} ;
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Socket Address Structure
Sockets
22
struct type1 {
int i;
int k;
} ;
struct type2 {
char arr1[2];
char arr2[6]
} ;
struct generic_type {
int i[2];
} ;
void fun(struct generic_type *p); Struct type1 tp1;
Struct type2 tp2;
fun( (struct generic_type *) &tp1);
fun( (struct generic_type *) &tp2);
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Internet socket address structure
Internet socket address structure
The structure is called sockaddr_in, defined in
Here is a version for IPv4:
typedef uint32_t in_addr_t;
typedef unsigned short sa_family_t; struct in_addr {
unit32_t s_addr;
};
struct sockaddr_in {
sa_family_t in_port_t struct in_addr char
sin_family; // AF_INET
sin_port; // 16-bit port number sin_addr; // 32-bit IPv4 address sin_zero[8]; // unused
};
Sockets
23
http://man7.org/linux/man-pages/man7/ip.7.html
man 7 ip
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Unix socket address structure
The structure is called sockaddr_un, defined in
Here is a version from Solaris:
struct sockaddr_un {
sa_family_t sun_family; char sun_path[108];
// AF_UNIX
// path name
};
Sockets
24
man 7 unix
https://linux.die.net/man/7/unix
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Generic Socket Address Structure
Socket address structures are always passed by address when passed as a parameter.
Because there are several kinds of socket structures, socket functions prototypes take a pointer to the generic socket address structure, which represents any socket address structure parameter.
The generic address structure is called sockaddr, defined in
Here is the definition of the structure:
struct sockaddr{
uint8_t sa_family_t
sa_len; sin_family;
char sa_data[14]; // protocol-specific address
};
man 2 bind
Sockets
25
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
The bind() system call
bind()
Synopsis:
int bind(int s, struct sockaddr *sp, int len);
Returns 0 when successful and -1 otherwise.
bind() assigns a local protocol address to a socket.
In case of the Internet, the protocol address consists of a 32-bit IPv4 address and a 16-bit port number.
bind() is usually called by a server to bind their local IP and a well-known port number to a socket.
Example
struct sockaddr in sv; // IPv4 socket
…
sd = socket(AF INET, SOCK STREAM, 0);
…
bind(sd, (struct sockaddr*)&sv, sizeof(sv));
Sockets
26
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
Internet socket address structure Unix socket address structure Generic Socket Address Structure
Example
Example
Example : The bind() function prototype is
int bind(int, struct sockaddr *, socklen t);
→ Any call to this function should cast the pointer to the
protocol-specific socket address structure to be a point to a generic socket address structure.
For example:
struct sockaddr_in sv; // IPv4 socket, server
:
bind(sfd, (struct sockaddr*)&sv, sizeof(sv));
Sockets
27
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
The connect() system call
connect()
Synopsis:
int connect(int s,struct sockaddr *srv,int len)
Returns 0 when successful and -1 otherwise.
connect() is used by a TCP client to establish a connection with a TCP server.
The parameters have the following meanings:
s is a socket descriptor that was returned by socket(). srv is a pointer to a socket address structure object, which must contain the IP address and port number of the server len is the size of the socket address structure.
connect() only returns when a connection is established or when an error occurs.
Sockets
28
man connect
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
The listen() system call
listen()
Synopsis: int listen(int s, int backlog);
Returns 0 when successful and -1 otherwise.
listen() is called only by a TCP server to accept connections from client sockets that will issue a connect().
s is a file descriptor of a socket that has been already created.
backlog defines the maximum length the queue of pending connections may grow to.
listen() is normally called after the calls to socket()
and bind().
Sockets
29
See notes in man listen
Copyright @ 2019, 2020, 2021 all rights reserved
Introducing Sockets Creating endpoints for communication: socket()
Socket Address Structures Initiating a connection on a socket: connect() Binding a name to a socket: bind()
Listening for connections on a socket: listen() Accepting a connection on a socket: accept()
The accept() system call
accept()
Synopsis:
int accept(int s, struct sockaddr *addr, socklen t *addrlen);
Returns a file descriptor for a new socket when successful and
-1 otherwise.
accept() is called by a TCP server to extract the first connection on the queue of pending connections, creates a new socket with the properties of s, and allocates a new file descriptor for the newly created socket.
If no pending connections are present on the queue, accept() blocks the caller until a connection is present. Usually, the file descriptor s is called the listening socket, while the returned value is called the connected socket.
Sockets
30
See man accept
Copyright @ 2019, 2020, 2021 all rights reserved