Sockets: Introduction
Prev: file-locking Next: sockets-unix-domain
Sockets are a method of IPC that allow data to be exchanged between applications, either on the same host or on different hosts connected by a network.
Overview
In a client-server scenario, applications communicate with sockets like so:
- An application creates a socket. Both sides require a socket.
- The server binds its socket to a well-known address (name) so that clients can locate it.
A socket is created with the socket
system call, which returns a file descriptor used to refer to the socket.
fd = socket(domain, type, protocol);
Communication domains
Sockets exist in communication domains, which determines:
- the way to identify the socket (the format)
- the range of communication (between the same host or between applications on different hosts)
Most systems have the following domains:
AF_UNIX
, for communication between applications on the same host.AF_INET
, communication between applications running on hosts connected on IPv4.AF_INET6
, communication between applications running on hosts connected on IPv6.
Summarized thusly:
Domain | Communication performed | Communication between applications | Address format | Address structure |
---|---|---|---|---|
AF_UNIX | within kernel | on same host | pathname | sockaddr_un |
AF_INET | via IPv4 | on hosts connected via an IPv4 network | 32-bit IPv4 address + 16-bit port number | sockaddr_in |
AF_INET6 | via IPv6 | on hosts connected | via an IPv6 network | 128-bit IPv6 address + 16-bit port number |
Each implementation also provides stream and datagram sockets, with the following characteristics:
Property | Stream | Datagram |
---|---|---|
Reliable delivery? | Y | N |
Message boundaries preserved? | N | Y |
Connection-oriented? | Y | N |
Socket System Calls
socket
creates a new socket.bind
binds a socket to an address, so clients can locate the socket.listen
to allow a stream socket to accept incoming connections from other sockets.accept
accepts a connection from a peer application on a listening socket stream.connect
establishes a connection with another socket.
#include <sys/socket.h>
int socket(int domain, int type, int protocol); // Returns file descriptor on success, or –1 on error
#include <sys/socket.h>
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); // Returns 0 on success, or –1 on error
struct sockaddr {
sa_family_t sa_family; /* Address family (AF_* constant) */
char sa_data[14]; /* Socket address (size varies according to socket domain) */
};
- Stream sockets are either active or passive. A socket created with
socket
is active, and can be used in aconnect
call to establish a connection to a passive socket. - A passive socket is one that has been marked to allow incoming connections by calling
listen
.
Stream Sockets
- The
socket
system call creates a socket, which is like a telephone (it allows for bidirectional communication). - One application calls
bind
to bind the socket,listen
to mark that it is ready for connections. - The other application establishes the connection with
connect
and the address of the other party. - The application that called
listen
accepts the connection usingaccept
. Accept blocks until the opposing party is ready withconnect
. - Data can be send using
send
andrecv
, and sockets can be closed withclose
.
#include <sys/socket.h>
int listen(int sockfd, int backlog); // Returns 0 on success, or –1 on error
Accept is used to accept an incoming connection. If there are no pending connections, the call blocks until one arrives.
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); // Returns file descriptor on success, or –1 on error
Connect connects the active socket to the listening socket on addr
and addrlen
.
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); // Returns 0 on success, or –1 on error
To shutdown a socket, close
or shutdown
can be used.
Datagram Sockets
Datagram sockets have a different flow.
- The socket system call is like setting up a mailbox, in a location where the postal service delivers and picks up letters to said mailbox.
- In order to allow another application to send it messages, an application uses
bind
, which allows messages to be sent to it. - To send a message, an application calls
sendto
, with the bound socket. - To receive a message, an application calls
recvfrom
, which blocks until a message is received. This also allows for replies, since sockets are labeled with their sending address. - Unneeded sockets are cleaned up with
close
.
Exchanging Datagrams: recvfrom
and sendto
#include <sys/socket.h>
ssize_t recvfrom(int sockfd, void *buffer, size_t length, int flags,
struct sockaddr *src_addr, socklen_t *addrlen); // Returns number of bytes received, 0 on EOF, or –1 on error
ssize_t sendto(int sockfd, const void *buffer, size_t length, int flags,
const struct sockaddr *dest_addr, socklen_t addrlen); // Returns number of bytes sent, or –1 on error
recvfrom
and sendto
work like recv
and send
.
Using connect
with datagram sockets
Using connect
on datagram sockets has the kernel give an address to a socket. This allows usage of read
and write
, but also makes calling easier by not requiring the address to be passed in every time.
Prev: file-locking Next: sockets-unix-domain