BSD sockets

BSD sockets

POSIX sockets es una parte de la especificación POSIX. POSIX son las siglas de Portable Operating System Interface, una familia de estándares especificados por el IEEE para mantener la compatibilidad entre sistemas operativos. POSIX define una API (Application Programming Interface) basada en la de los sistemas UNIX, precisamente para asegurar la compatibilidad entre las distintas variantes de UNIX y otros sistemas operativos. POSIX sockets define una parte de API POSIX dedicada a la comunicación entre procesos, fundamentalmente entre equipos conectados a través de Internet (socket de Internet), aunque también soporta la conexión local entre procesos que se ejecutan en el mismo sistema —socket de dominio UNIX o socket UNIX—.

Historia

La primera implementación ampliamente distribuida de la pila de protocolos TCP/IP lo fue con el UNIX 4.2BSD, que incluía BSD sockets (o Berkeley sockets) como API para las comunicaciones entre procesos usando estos protocolos.

Las distintas versiones de BSD incorporaban código del UNIX original de AT&T, por lo que estaban sujetas a la licencia de software de esta empresa. La licencias de código fuente se estaban volviendo muy costosas, por lo que muchas empresas y organizaciones comenzaron a interesarse en la liberación independiente del código de red, que había sido desarrollado enteramente al margen de AT&T, por lo que no tenía que estar sujeto a los requerimientos de su licencia.

En junio de 1989 este código fue liberado bajo los términos de la licencia BSD. Muchos fabricantes incluyeron este código directamente en sus propios sistemas, incluso aunque tuvieran sus propios protocolos propietarios con los que competían entre ellos. Y algunas compañías comenzaron a utilizarlo para vender pilas de protocolo TCP/IP para Windows, hasta que Microsoft incluyó la suya propia en Windows 95, también derivada del código de BSD.

Todo esto alimentó el despegue de TCP/IP como protocolo dominante e impuso los BSD sockets como API de acceso a la red, de tal forma que hoy en día todos los sistemas operativos modernos tienen una implementación de BSD sockets.

La API BSD sockets evolucionó y finalmente fue adoptado en el estándar POSIX1, donde algunas funciones fueron deprecadas y eliminadas y reemplazadas por otras. Aun así, la API POSIX sockets es básicamente la BSD sockets.

De la misma manera, los sistemas Windows incluyen Winsock, una API de acceso a la red derivada de BSD sockets, que solo difiere de esta en unos pocos detalles

Funciones del API

Este es un resumen de las funciones proporcionadas por POSIX sockets:

  • socket() Crea un nuevo socket —identificado por un número entero— y reserva recursos del sistema para él.

  • bind() Se usa generalmente en el lado del servidor para asociar un socket con una dirección de red. Por ejemplo, una dirección IP y un puerto concretos.

  • listen() Se usa en el lado del servidor para hacer que un socket TCP entre en modo de escucha, a la espera de nuevas conexiones entrantes.

  • connect() Se usa en el lado del cliente para asignar un número de puerto libre al socket. En el caso de socket TCP, intenta establecer una nueva conexión TCP con un socket a la escucha en otro puerto y dirección IP.

  • accept() Se usa en el lado del servidor para aceptar una conexión entrante e intentar crear una nueva conexión TCP con el cliente remoto. Si tiene éxito, produce un nuevo socket asociado con esta pareja concreta de direcciones en ambos extremos de la conexión.

  • send() y recv(), write() y read() o sendto() y recvfrom() Se utilizan para enviar y recibir datos hacia y desde el otro extremo de la conexión.

  • close() Hace que el sistema libere los recursos asignados al socket. En el caso de conexiones TCP, esta es finalizada.

  • getaddrinfo() y getnameinfo() Se usan para resolver nombres de máquina y direcciones IP (DNS).

  • select() Se usa para esperar a que uno o más sockets de una lista estén listos para leer, escribir o tengan algún error.

  • poll() Se usa para comprobar el estado de los sockets en un conjunto de sockets. Puede comprobar si están listos para escribir, leer o si ha ocurrido algún error.

  • getsockopt() Se utiliza para recuperar el valor actual de una opción concreta de configuración del socket especificado.

  • setsockopt() Se emplea para cambiar el actual de una opción concreta de configuración del socket especificado.

POSIX API en Boost.Asio

Boost.Asio es una librería de C++ para programadores de software de sistema donde el acceso a funcionalidades del sistema operativo —como la red, los archivos, un puerto serie, etc.— se requiere con cierta frecuencia. El acceso a estos recursos suele implicar operaciones de E/S que normalmente consumen mucho tiempo antes de completarse, por lo que Boost.Asio provee herramientas para gestionar estas conexiones de manera asíncrona, sin necesitar modelos de concurrencia basados en hilos o en múltiples procesos y memoria compartida.

Debido a que uno de los usos principales de esta librería son las comunicaciones por red, Boost.Asio incluye una interfaz multiplataforma de sockets de bajo nivel —basada en la API BSD sockets— implementada sobre la que proporciona el propio sistema operativo.

A diferencia de esta última, la implementación proporcionada por Boost.Asio no incluye algunos aspectos del API original que no son seguros o que son propensos a provocar errores de programación. Por ejemplo, el uso de int para identificar a los sockets por parte del API BSD sockets carece de la seguridad que nos ofrecería tener un tipo específico para ellos. Por eso la representación de un socket en Boost.Asio usa un tipo distinto para cada protocolo. Por ejemplo, para TCP el tipo de un socket es ip::tcp::socket mientras para UDP el tipo es ip::udp::socket.

En la documentación de Boost.Asio se incluye una tabla que muestra la relación entre la API BSD socket y la API de acceso a red de Boost.Asio:

Referencias