Há cerca de 18 meses, escrevi um blog falando sobre as mudanças na forma como o accept funciona na versão 17.1 do OpenVOS. O que eu não mencionei foi que essas mudanças só entram em vigor se o código do aplicativo for baseado em POSIX. Para recapitular, antes da versão 17.1, o STCP só respondia a uma solicitação de conexão do cliente se o código do aplicativo do servidor tivesse chamado a rotina accept. Se o código não tivesse chamado o accept, a solicitação de conexão do cliente entraria em uma fila, mas não seria respondida. Assim que o aplicativo chamasse o accept, o STCP enviaria uma resposta de conexão. Se o cliente ainda estivesse aguardando, a conexão seria concluída naquele momento. Se o cliente já tivesse desistido, ele responderia à resposta de conexão com um reset, o STCP descartaria a conexão e o accept ficaria pendente (supondo o modo de bloqueio) e aguardaria outra conexão.
A Figura 1 mostra esse cenário; as linhas de texto alinhadas à esquerda são mensagens de status do aplicativo do servidor, as linhas recuadas packet_monitor (ligeiramente modificadas) são o resultado da atividade do cliente. O aplicativo (acceptTestnoPosix) é iniciado e fica à escuta na porta 12345 e, uma vez em escuta, entra em modo de espera por 300 segundos. O cliente então faz uma conexão com a porta 12345 enviando um segmento TCP para a porta 12345 com o sinalizador Syn (S) definido. Ele tenta três vezes antes de desistir. Após 300 segundos, o aplicativo acorda e chama accept. A pilha STCP responde ao cliente com um segmento TCP com os sinalizadores Syn e Ack (SA) definidos. Como o cliente não tem mais um registro da conexão, se enviar um Reset (R), o STCP bloqueia neste ponto. Se o soquete estivesse no modo não bloqueante, o accept teria retornado com um erro EAGAIN.
acceptTestnoPosix 12345 Executando acceptTestnoPosix 12345 Em espera por 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 Pronto para aceitar uma conexão na porta 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 – aceitar pré 17.1 ou pós 17.1 não POSIX
Se o aplicativo for baseado em POSIX, as coisas são diferentes (Figura 2). O STCP responde à solicitação de conexão (S) imediatamente (SA). Então, após 300 segundos, o aplicativo é ativado, chama accept e o STCP retorna o soquete aceito.
acceptTestwithPosix 12345 Executando acceptTestnoPosix 12345 Em espera por 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 Pronto para aceitar uma conexão na porta número 12345 Conexão aceita |
Figura 2 – aceitar postagem baseada em POSIX 17.1
A diferença de comportamento pode ser crítica. Se o cliente estiver esperando uma resposta do aplicativo servidor após estabelecer uma conexão, ele pode expirar e fechar a conexão antes que o aplicativo realmente chame accept.
Como você cria um aplicativo com POSIX? Primeiro, a linha
#define _POSIX_C_SOURCE 200112L |
deve ser a primeira linha do código-fonte do aplicativo. Em segundo lugar, o caminho da biblioteca
(disco_mestre)>sistema>biblioteca_de_objetos_posix
precisa estar nos caminhos da biblioteca de objetos após as bibliotecas STCP e antes da biblioteca C.
Como você pode saber se isso foi feito? Bem, você pode verificar as bibliotecas de objetos às quais o aplicativo foi vinculado usando o comando display_program_module -object_dirs.
display_program_module acceptTestwithPosix -object_dirs
%azvos#m17_mas>SysAdmin>Noah_Davids>temp>acceptTestwithPosix.pm
Mapa do diretório de objetos:
11 diretórios de pesquisa
0 diretórios sem pesquisa
11 diretórios no total
DTC Caminho do diretório
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>system>object_library
9 %azvos#m17_mas>opt>apache>lib
10 %azvos#m17_mas>opt>openssl>lib
11 %azvos#m17_mas>opt>mysql>lib>mysql
|
Mas isso não indica se o #define faz parte do código-fonte.
Se você puder executar o código, poderá verificar os sinalizadores do soquete. Um programa baseado em POSIX terá o sinalizador de soquete SF_POSIX definido. Por exemplo, tenho três programas: acceptTestnoPosix, acceptTestwithPosix e acceptTestwithPosixPathOnly. O último tinha o diretório >system>posix_object_library nos caminhos da biblioteca, mas não incluía o #define no código-fonte. Observe que essa combinação é considerada inválida. Somente o aplicativo que estava vinculado à biblioteca POSIX e tinha a instrução #define POSIX_SOURCE no código criou um soquete com o sinalizador SF_POSIX.
acceptTestnoPosix.pm 12345 Executando acceptTestnoPosix 12345 Em espera por 300 segundos como: match posix; dump_stcbq -full -lport 12345 como: |
acceptTestwithPosix.pm 12345
Executando acceptTestnoPosix 12345
Em espera por 300 segundos
como: match posix; dump_stcbq -full -lport 12345
SF_POSIX
como:
|
acceptTestwithPosixPathOnly.pm 12345 Executando acceptTestnoPosix 12345 Em espera por 300 segundos como: match posix; dump_stcbq -full -lport 12345 como: |
Há uma quarta possibilidade: o #define foi incluído na fonte, mas a posix_object_library não foi usada. Nesse caso, a rotina do soquete retornará um erro.
acceptTestwithPosixDefineOnly 12345 Executando acceptTestnoPosix 12345 acceptTestnoPosix: não é possível criar soquete de escuta: Aplicativo compilado incorretamente: o tempo de execução POSIX deve ser pesquisado antes do tempo de execução C. |
Todos os comandos e utilitários do STCP são criados com POSIX e recomendo fortemente que todos os aplicativos que você criar também utilizem POSIX.
