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
socketcreates a new socket.bindbinds a socket to an address, so clients can locate the socket.listento allow a stream socket to accept incoming connections from other sockets.acceptaccepts a connection from a peer application on a listening socket stream.connectestablishes 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 errorstruct 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
socketis active, and can be used in aconnectcall 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
socketsystem call creates a socket, which is like a telephone (it allows for bidirectional communication). - One application calls
bindto bind the socket,listento mark that it is ready for connections. - The other application establishes the connection with
connectand the address of the other party. - The application that called
listenaccepts the connection usingaccept. Accept blocks until the opposing party is ready withconnect. - Data can be send using
sendandrecv, and sockets can be closed withclose.
#include <sys/socket.h>
int listen(int sockfd, int backlog); // Returns 0 on success, or –1 on errorAccept 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 errorConnect 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 errorTo 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 errorrecvfrom 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