Ir al contenido principal

Hace unos 18 meses escribí un blog hablando de los cambios en el funcionamiento de accept en la versión 17.1 de OpenVOS. Lo que olvidé indicar es que estos cambios sólo tienen efecto si el código de la aplicación está basado en POSIX. Para recapitular, antes de la 17.1 STCP sólo respondía a una solicitud de conexión de cliente si el código de la aplicación del servidor había llamado a la rutina de aceptación. Si el código no había llamado a la rutina de aceptación, la solicitud de conexión del cliente entraría en una cola pero no sería respondida. Una vez que la aplicación llamada "accept" (aceptar), STCP enviaría una respuesta de conexión. Si el cliente sigue esperando, la conexión se completa en ese momento. Si el cliente ya se había rendido, respondería a la respuesta de la conexión con un restablecimiento, STCP tiraría la conexión y el aceptar se colgaría (asumiendo el modo de bloqueo) y esperaría otra conexión.

La figura 1 muestra este escenario; las líneas de texto justificadas a la izquierda son mensajes de estado de la aplicación del servidor, las líneas sangradas packet_monitor (ligeramente modificadas) son el resultado de la actividad del cliente. La aplicación (acceptTestnoPosix) se inicia y escucha en el puerto 12345, y una vez que se escucha se duerme durante 300 segundos. El cliente entonces hace una conexión al puerto 12345 enviando un segmento TCP al puerto 12345 con la bandera Syn (S) puesta. Lo intenta tres veces antes de rendirse. Después de 300 segundos la aplicación se despierta y las llamadas son aceptadas. La pila STCP responde al cliente con un segmento TCP con los flags Syn y Ack (SA) activados. Como el cliente ya no tiene registro de la conexión si envía un Reset (R), STCP se bloquea en este punto. Si el socket estuviera en modo no bloqueante, aceptar habría vuelto con un error EAGAIN.

acceptTestnoPosix 12345
Ejecutando acceptTestnoPosix 12345
Dormir 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 - aceptar pre 17.1 o no POSIX post 17.1

 

Si la aplicación está basada en POSIX, las cosas son diferentes (Figura 2). STCP responde a la solicitud de conexión (S) inmediatamente (SA). Luego, después de 300 segundos la aplicación se despierta, las llamadas se aceptan y STCP devuelve el socket aceptado.

Acepte la prueba con la casilla 12345
Ejecutando acceptTestnoPosix 12345
Dormir 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 el puesto basado en POSIX 17.1

 

La diferencia de comportamiento puede ser crítica. Si el cliente espera una respuesta de la aplicación del servidor después de hacer una conexión, puede que se agote el tiempo de espera y se cierre la conexión antes de que la aplicación llame a aceptar.

¿Cómo se construye una aplicación con POSIX? Primero la línea

#define _POSIX_C_SOURCE 200112L

debería ser la primera línea de la fuente de la aplicación. Segundo la ruta de la biblioteca

(master_disk)>sistema>biblioteca_de_objetos_de_posiciones

necesita estar en las rutas de las librerías de objetos después de las librerías STCP y antes de la librería C.

¿Cómo puedes saber si esto se ha hecho? Bueno, puedes mirar las librerías de objetos con las que la aplicación estaba enlazada usando el comando display_program_module -object_dirs

display_program_module acceptTestwithPosix -object_dirs      
     SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm 

Mapa del Directorio de Objetos:

    11 directorios de búsqueda
     0 directorios de no búsqueda
    11 directorios en total

   Ruta de Directorio DTC

     1 %azvos#m17_mas>SysAdmin>Noah_Davids>temp
     2 %azvos#m17_mas>sistema>stcp>object_library
     3 %azvos#m17_mas>sistema>stcp>object_library>socket
     4 %azvos#m17_mas>sistema>stcp>object_library>net
     5 %azvos#m17_mas>sistema>stcp>biblioteca de objetos>común
     6 %azvos#m17_mas>system>posix_object_library
     7 %azvos#m17_mas>sistema>c_object_library
     8 %azvos#m17_mas>sistema>object_library
     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 dice si el #definido es parte del código fuente.

Si puedes ejecutar el código puedes mirar las banderas de los sockets, un programa basado en POSIX tendrá la bandera de los sockets 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 la biblioteca pero no incluía el #define en el código fuente. Tenga en cuenta que esto se considera una combinación inválida. Sólo la aplicación que estaba enlazada con la biblioteca POSIX y tenía la sentencia POSIX_SOURCE #define en el código creó un socket con la bandera SF_POSIX.

acceptTestnoPosix.pm 12345     
Ejecutando acceptTestnoPosix 12345
Dormir durante 300 segundos
               as: match posix; dump_stcbq -full -lport 12345     
               como:
Acepte la prueba con Posix.pm 12345
Ejecutando acceptTestnoPosix 12345
Dormir durante 300 segundos
               as: match posix; dump_stcbq -full -lport 12345
                                                   SF_POSIX
               como:  
Acepte la prueba con PosixPathOnly.pm 12345
Ejecutando acceptTestnoPosix 12345
Dormir durante 300 segundos
               as: match posix; dump_stcbq -full -lport 12345
               como:

Hay una cuarta posibilidad, la #definición fue incluida en la fuente pero la biblioteca posix_object_library no fue usada. En este caso la rutina del socket devolverá un error.

Acepte la prueba con PosixDefineOnly 12345
Ejecutando acceptTestnoPosix 12345
acceptTestnoPosix: no se puede crear una toma de escucha: Aplicación construida  
+ incorrectamente: El tiempo de ejecución POSIX debe ser buscado antes del tiempo de ejecución C.

Todos los comandos y utilidades de STCP están construidos con POSIX y recomiendo encarecidamente que cualquier aplicación que construya también use POSIX.