Los sockets proporcionan una comunicación de dos vías, punto a punto entre dos procesos. Los sockets son muy versátiles y son un componente básico de comunicación entre interprocesos e intersistemas. Un socket es un punto final de comunicación al cual se puede asociar un nombre. Este tiene un tipo y uno o más procesos asociados.
Los sockets existen en los dominios de comunicación. Un socket de dominio es una representación que da una estructura de direccionamiento y un conjunto de protocolos. Los sockets se conectan solamente con sockets en el mismo dominio. Veintitrés dominios de sockets son identificados (ver <sys/socket.h>), de los cuales solamente los dominios de UNIX e Internet son normalmente sockets de Linux usados para comunicarse entre procesos en un sólo sistema, como otras formas de comunicación entre procesos.
El dominio de UNIX da un espacio de direcciones de socket en un sistema. Los sockets de dominio de UNIX son nombrados con las rutas de UNIX. Los sockets pueden también ser usados para comunicar procesos entre diferentes sistemas. El espacio de direcciones del socket entre los sistemas conectados es llamado el dominio de Internet.
La comunicación del dominio de Internet usa la suite del protocolo de Internet TCP/IP.
Los tipos de socket definen las propiedades de comunicación visibles para la aplicación. Los procesos se comunican solamente entre los sockets del mismo tipo. Existen cinco tipos de sockets.
Los sockets son usualmente datagramas orientados, pero sus características exactas dependen de la interfaz dada por el protocolo.
Se llama a la función int socket(int dominio, int tipo, int protocolo); para crear un extremo de una comunicación (socket) en el dominio especificado y del tipo indicado. Si un protocolo no es especificado. el sistema usa uno predefinido que soporte el tipo de socket especificado. El manejador del socket (un descriptor) es devuelto. Un proceso remoto no tiene forma de identificar un socket hasta que una dirección se ligada a este. Los procesos de comunicación se conectan a través de direcciones. En el dominio de UNIX, una conexión esta compuesta usualmente de uno o dos nombres de rutas. En el dominio de Internet, una conexión esta compuesta de direcciones locales y remotas y partes locales y remotas. En muchos dominios, las conexiones deben ser únicas.
Se llama a la función int bind(int sockfd, struct sockaddr *nomb, socklen_t longdir) para enlazar un camino o una dirección de Interne a un conector (socket). Hay tres formas diferentes de llamar a bind(), dependiendo del dominio del socket.
#include <sys/socket.h> ... bind (sd, (struct sockaddr *) &direccion, longitud);
#include <sys/un.h> ... bind (sd, (struct sockaddr_un *) &direccion, longitud);
#include <net/netinet.h> ... bind (sd, (struct sockaddr_in *) &direccion, longitud);
En el dominio de UNIX, el enlazado de nombres crea un socket con nombre en el sistema de archivos. Usar unlink() or rm() para eliminar el socket.
La conexión de sockets es usualmente asimétrica. Un proceso usualmente actúa como un servidor y el otro proceso es el cliente. El servidor enlaza su socket a un camino o dirección previamente acordada, y entonces bloquea el socket. Para un conetor SOCK_STREAM, el servidor llama a la función int listen(int s, int backlog), para indicar cuantas peticiones de conexión serán puestas en la cola. Un cliente inicia la conexión al socket del servidor mediante una llamada a la función int connect(inst s, struct sockaddr *nomb_serv, int longdirec). Una llamada en el dominio de UNIX es como la siguiente:
struct sockaddr_un server; ... connect ( sd, (struc sockaddr_un *)&server, long);
mientras en el dominio de Internet la llamada podría ser:
struct sockaddr_in server; ... connect ( sd, (struc sockaddr_un *)&server, long);
Si el socket del cliente no esta enlazado al momento de hacer la llamada para la conexión, el sistema automáticamente selecciona y liga un nombre al socket. Para un socket SOCK_STREAM, el servidor llama a la función accept() para completar la conexión.
La función int accept(int s, struct sockaddr *addr, int *longdirec) regresa un conector nuevo el cual es válido solamente para la conexión particular. Un servidor puede tener múltiples conexiones SOCK_STREAM activas al mismo tiempo.
Se emplean varias funciones para enviar y recibir datos de un socket SOCK_STREAM. Estas son write(), read(), int send(int s, const void *msg, size_t lon, int flags), y int recv(int s, void *buf, size_t lon, int flags). Las funciones send() y recv() son parecidas a read() y write(), pero tienen algunas banderas operacionales adicionales.
El argumento flags de una llamada a recv se forma aplicando el operador de bits O-lógico a uno o más de los valores siguientes: