¿Cómo utilizar TCP_NODELAY?

written by uve 2 April 2012

Llevaba cerca de dos días con un problema implementando el subscriptor MQTT. Aún no está hecho el diagrama de flujo ya que de momento estoy probando que las llamadas de la biblioteca funcionan. El escenario es el siguiente:

  1. mqtt_connect
  2. mqtt_subscribe
  3. mqtt_unsubscribe
  4. mqtt_disconnect

Conectamos el cliente, nos subscribimos a un topic, nos desubscribimos y desconectamos el cliente. Algo que a priori es sencillamente elemental.

Para comprobar que todo esto funciona he hecho uso del script para Wireshark que ya comenté. Pero el caso es que estaba encontrando errores en Wireshark que no eran lógicos. Yo mandaba un paquete de 17bytes y Wireshark decía que el paquete tenía 19bytes. ¿Qué estaba pasando aquí?

Después de volverme casi loco me acabo de dar cuenta que por algún motivo subscribe y unsubscribe viajaban en el mismo paquete TCP en lugar de dos paquetes distintos. Este motivo es el algoritmo de Nagle.

Lo primero que pensé es utilizar fflush para evitar este comportamiento, pero los sockets TCP no lo soportan. Sí lo soportan en cambios los archivos regulares e incluso los sockets UNIX. Así que la solución pasa por deshabilitar el algoritmo de Nagle. Para ello se hace uso del flag TCP_NODELAY.

Veamos cómo hacer esto en C:

int socket_id;
if((socket_id = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    // Error

int flag = 1;
if (setsockopt(socket_id, IPPROTO_TCP, TCP_NODELAY, (char*) &flag, sizeof(flag)) < 0)
    // Error

Para utilizar TCP_NODELAY es necesario incluir la siguiente cabecera:

#include <linux/tcp.h>

Importante: TCP_NODELAY es para un propósito muy específico: deshabilitar el algoritmo de Nagle. Sólo se debe establecer para las aplicaciones que envían pequeñas ráfagas frecuentes de información sin obtener una respuesta inmediata, donde se requiere la entrega oportuna de los datos.

Source

https://github.com/menudoproblema/menudoproblema-examples/blob/master/c/sockets/nagle.c

Tags

La teoría es cuando crees saber algo, pero no funciona.
La práctica es cuando algo funciona, pero no sabes por qué.
Los programadores combinan la teoría y la práctica:
Nada funciona y no saben por qué.