Hace unos 18 meses escribí una entrada en el blog en la que hablaba de los cambios en el funcionamiento de «accept» en la versión 17.1 de OpenVOS. Lo que no señalé fue que estos cambios solo surten efecto si el código de la aplicación está basado en POSIX. En resumen, antes de la versión 17.1, STCP solo respondía a una solicitud de conexión del cliente si el código de la aplicación del servidor había llamado a la rutina «accept». Si el código no había llamado a «accept», la solicitud de conexión del cliente entraba en una cola, pero no recibía respuesta. Una vez que la aplicación llamaba a «accept», STCP enviaba una respuesta de conexión. Si el cliente seguía esperando, la conexión se completaba en ese momento. Si el cliente ya se había dado por vencido, respondía a la respuesta de conexión con un reinicio, STCP descartaba la conexión y «accept» se quedaba bloqueado (suponiendo que estuviera en modo de bloqueo) y esperaba otra conexión.
La figura 1 muestra este escenario; las líneas de texto alineadas a la izquierda son mensajes de estado de la aplicación del servidor, mientras que las líneas de packet_monitor (ligeramente modificadas) que aparecen sangradas son el resultado de la actividad del cliente. La aplicación (acceptTestnoPosix) se inicia y escucha en el puerto 12345, y una vez que está a la escucha, entra en suspensión durante 300 segundos. A continuación, el cliente establece una conexión con el puerto 12345 enviando un segmento TCP al puerto 12345 con la bandera Syn (S) activada. Lo intenta tres veces antes de darse por vencido. Tras 300 segundos, la aplicación se activa y llama a accept. La pila STCP responde al cliente con un segmento TCP con las banderas Syn y Ack (SA) activadas. Dado que el cliente ya no tiene un registro de la conexión, envía un Reset (R), por lo que STCP se bloquea en este punto. Si el socket estuviera en modo no bloqueante, accept habría devuelto un error EAGAIN.
acceptTestnoPosix 12345 Ejecutando acceptTestnoPosix 12345 En espera durante 300 segundos 11:04:45.923 R TCP 164.152.77.50 164.152.77.217 11071 12345 S 11:04:48.925 R TCP 164.152.77.50 164.152.77.217 11071 12345 S 11:04:54.937 R TCP 164.152.77.50 164.152.77.217 11071 12345 S Listo para aceptar una conexión en el puerto número 12345 11:09:41.852 T TCP 164.152.77.217 164.152.77.50 12345 11071 SA 11:09:41.854 R TCP 164.152.77.50 164.152.77.217 11071 12345 R |
Figura 1: acepta versiones anteriores a la 17.1 o versiones posteriores a la 17.1 que no sean POSIX
Si la aplicación está basada en POSIX, el proceso es diferente (Figura 2). STCP responde inmediatamente a la solicitud de conexión (S) (SA). A continuación, tras 300 segundos, la aplicación se activa, llama a «accept» y STCP devuelve el socket aceptado.
acceptTestwithPosix 12345 Ejecutando acceptTestnoPosix 12345 En espera durante 300 segundos 10:58:43.962 R TCP 164.152.77.50 164.152.77.217 11024 12345 S 10:58:43.964 T TCP 164.152.77.217 164.152.77.50 12345 11024 SA 10:58:43.964 R TCP 164.152.77.50 164.152.77.217 11024 12345 A Listo para aceptar una conexión en el puerto número 12345 Conexión aceptada |
Figura 2: aceptar publicaciones basadas en POSIX a partir de la versión 17.1
La diferencia de comportamiento puede ser crucial. Si el cliente espera una respuesta de la aplicación del servidor tras establecer una conexión, es posible que se agote el tiempo de espera y se cierre la conexión antes de que la aplicación llame realmente a la función «accept».
¿Cómo se crea una aplicación con POSIX? En primer lugar, la línea
#define _POSIX_C_SOURCE 200112L |
debe ser la primera línea del código fuente de la aplicación. En segundo lugar, la ruta de la biblioteca
(master_disk)>sistema>biblioteca_de_objetos_posix
debe figurar en las rutas de la biblioteca de objetos después de las bibliotecas STCP y antes de la biblioteca C.
¿Cómo se puede saber si esto se ha hecho? Pues bien, puedes consultar las bibliotecas de objetos a las que se vinculó la aplicación mediante el comando `display_program_module -object_dirs`.
display_program_module acceptTestwithPosix -object_dirs
%azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm
Mapa de directorios de objetos:
11 directorios de búsqueda
0 directorios que no se buscan
11 directorios en total
DTC Ruta del directorio
1 %azvos#m17_mas>SysAdmin>Noah_Davids>temp
2 %azvos#m17_mas>system>stcp>object_library
3 %azvos#m17_mas>system>stcp>object_library>socket
4 %azvos#m17_mas>system>stcp>object_library>net
5 %azvos#m17_mas>system>stcp>object_library>common
6 %azvos#m17_mas>system>posix_object_library
7 %azvos#m17_mas>system>c_object_library
8 %azvos#m17_mas>sistema>biblioteca_de_objetos
9 %azvos#m17_mas>opt>apache>lib
10 %azvos#m17_mas>opt>openssl>lib
11 %azvos#m17_mas>opt>mysql>lib>mysql
|
Pero esto no te indica si el #define forma parte del código fuente.
Si puedes ejecutar el código, puedes comprobar los indicadores del socket; un programa basado en POSIX tendrá activado el indicador SF_POSIX. Por ejemplo, tengo tres programas: acceptTestnoPosix, acceptTestwithPosix y acceptTestwithPosixPathOnly. Este último tenía el directorio >system>posix_object_library en las rutas de las bibliotecas, pero no incluía la definición #define en el código fuente. Ten en cuenta que esto se considera una combinación no válida. Solo la aplicación que estaba vinculada a la biblioteca POSIX y tenía la instrucción #define POSIX_SOURCE en el código creó un socket con el indicador SF_POSIX.
acceptTestnoPosix.pm 12345
Ejecutando acceptTestnoPosix 12345
En espera durante 300 segundos
como: match posix; dump_stcbq -full -lport 12345
como:
|
acceptTestwithPosix.pm 12345\
Ejecutando acceptTestnoPosix 12345\
En espera durante 300 segundos\
como: match posix; dump_stcbq -full -lport 12345
SF_POSIX
como:
|
acceptTestwithPosixPathOnly.pm 12345
Ejecutando acceptTestnoPosix 12345
En espera durante 300 segundos
como: match posix; dump_stcbq -full -lport 12345
como:
|
Existe una cuarta posibilidad: el #define se incluyó en el código fuente, pero no se utilizó la biblioteca posix_object_library. En este caso, la rutina de sockets devolverá un error.
acceptTestwithPosixDefineOnly 12345 Ejecutando acceptTestnoPosix 12345 acceptTestnoPosix: no se puede crear el socket de escucha: la aplicación se ha compilado + de forma incorrecta: se debe buscar el tiempo de ejecución POSIX antes que el tiempo de ejecución C. |
Todos los comandos y utilidades de STCP están desarrollados según POSIX, por lo que recomiendo encarecidamente que cualquier aplicación que desarrolles también utilice POSIX.
