estou testando coisas com soquetes e encontrei esse caso estranho:
Eu codifiquei um servidor tcp muito simples em c, bloqueei depois de aceitar (), apenas para ver o que acontece ao aceitar várias tentativas de conexão ao mesmo tempo:
Aqui está um trecho do código do servidor:
//listen()
if( (listen(sock,5)) == -1) {
perror("listen");
exit(-1);
}
//accept()
if( (cli = accept(sock, (struct sockaddr *) &client, &len)) == 1 ){
perror("accept");
exit(-1);
}
printf("entrez un int : ");
scanf("%d",&toto);
quando o servidor pede ao usuário para inserir um número inteiro, tento conectar vários clientes com telnet.
Para o primeiro, está tudo ok:
root@[...] :/home/[...]/workspace/sockets# netstat -antp | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 25832/toto
tcp 0 0 127.0.0.1:10003 127.0.0.1:51166 ESTABLISHED 25832/toto
tcp 0 0 127.0.0.1:51166 127.0.0.1:10003 ESTABLISHED 25845/telnet
mas depois do primeiro, mesmo sendo root, existem algumas conexões que não consigo ver o processo que o possui e seu pid:
root@[...] :/home/[...]/workspace/sockets# netstat -antp | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 25832/toto
tcp 0 0 127.0.0.1:10003 127.0.0.1:51166 ESTABLISHED 25832/toto
tcp 0 0 127.0.0.1:51166 127.0.0.1:10003 ESTABLISHED 25845/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:51168 ESTABLISHED -
tcp 0 0 127.0.0.1:51168 127.0.0.1:10003 ESTABLISHED 25852/telnet
um terceiro:
root@[...] :/home/[...]/workspace/sockets# netstat -antp | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 25832/toto
tcp 0 0 127.0.0.1:10003 127.0.0.1:51166 ESTABLISHED 25832/toto
tcp 0 0 127.0.0.1:51166 127.0.0.1:10003 ESTABLISHED 25845/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:51172 ESTABLISHED -
tcp 0 0 127.0.0.1:10003 127.0.0.1:51168 ESTABLISHED -
tcp 0 0 127.0.0.1:51168 127.0.0.1:10003 ESTABLISHED 25852/telnet
tcp 0 0 127.0.0.1:51172 127.0.0.1:10003 ESTABLISHED 25860/telnet
Tentei novamente alguns dias depois com netstat -antpe como root e aqui está o que consegui:
root@[...] :/home/[...]/workspace/sockets# netstat -antpe | grep 10003
tcp 0 0 0.0.0.0:10003 0.0.0.0:* LISTEN 1000 327680 22399/toto
tcp 0 0 127.0.0.1:33286 127.0.0.1:10003 ESTABLISHED 1000 417202 22884/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:33046 ESTABLISHED 0 0 -
tcp 0 0 127.0.0.1:10003 127.0.0.1:33286 ESTABLISHED 0 0 -
tcp 0 0 127.0.0.1:33044 127.0.0.1:10003 ESTABLISHED 1000 332810 22402/telnet
tcp 0 0 127.0.0.1:33046 127.0.0.1:10003 ESTABLISHED 1000 331200 22410/telnet
tcp 0 0 127.0.0.1:10003 127.0.0.1:33044 ESTABLISHED 1000 332801 22399/toto
como é que um processo ou uma conexão pode ter um inode de 0? Alguém pode me explicar o que está acontecendo?
O código do servidor chama
accept()
apenas uma vez. Assim, apenas a primeira tentativa de conexão é efetivamente aceita e as demais conexões do cliente são mantidas em uma fila de solicitações de conexão que reside no espaço do kernel. A próxima conexão do cliente será recuperada da fila quandoaccept()
for chamada novamente.Nenhum processo possui conexões de cliente enquanto permanecem no espaço do kernel, porque vários processos ou threads podem aceitar legalmente conexões de um par exclusivo de endereço e porta se habilitarem
SO_REUSEPORT
a opção em todos os descritores de soquete participantes.Você mesmo pode testar a
SO_REUSEPORT
opção adicionando o seguinte trecho de código antes dabind()
chamada e executando mais de um servidor. Você descobrirá que o kernel distribuirá as solicitações entre eles.Referência de
man 2 accept
:Referência de
man 7 socket
: