sudo netstat - antp não mostrando PID

0

Estou testando coisas com sockets e encontrei aquele caso estranho:

eu codifiquei muito simples servidor tcp em c, eu fiz isso bloco depois de aceitar (), só 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 digitar um número inteiro, eu tento conectar vários clientes com o telnet.

Fort o primeiro, tudo está bem:

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, apesar de eu ser root, existem algumas conexões que eu não posso ver o processo possuindo ele 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

Eu tentei novamente alguns dias depois com netstat -antpe como root e aqui está o que eu recebi:

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?

    
por joseph M'Bimbi-Bene 27.01.2018 / 09:47

1 resposta

0

O código do servidor chama accept() apenas uma vez. Assim, somente a primeira tentativa de conexão é efetivamente aceita e as conexões de clientes restantes são mantidas em uma fila de pedidos de conexão que vive no espaço do kernel. A próxima conexão do cliente será recuperada da fila quando accept() for chamado novamente.

Nenhum processo possui conexões de cliente enquanto elas permanecem no espaço do kernel, porque vários processos ou encadeamentos podem aceitar legalmente conexões de um par exclusivo de endereço e porta se habilitarem a opção SO_REUSEPORT em todos os descritores de soquete participantes.

Você pode testar a opção SO_REUSEPORT sozinho adicionando o seguinte snippet de código antes da chamada bind() e executando mais de um servidor. Você vai descobrir que o kernel irá distribuir pedidos entre eles.

{
    int enabled = -1;
    if (setsockopt (sockd, SOL_SOCKET, SO_REUSEPORT,
        (void*) &enabled, sizeof (enabled)) < 0) {
        perror ("setsockopt");
    }
}

Referência de man 2 accept :

The accept(sockfd) system call is used with connection-based socket types (SOCK_STREAM, SOCK_SEQPACKET). It extracts the first connection request on the queue of pending connections for the listening socket, sockfd, creates a new connected socket, and returns a new file descriptor referring to that socket. The newly created socket is not in the listening state. The original socket sockfd is unaffected by this call.

Referência de man 7 socket :

SO_REUSEPORT (since Linux 3.9)

Permits multiple AF_INET or AF_INET6 sockets to be bound to an identical socket address. This option must be set on each socket (including the first socket) prior to calling bind(2) on the socket. To prevent port hijacking, all of the processes binding to the same address must have the same effective UID. This option can be employed with both TCP and UDP sockets.

For TCP sockets, this option allows accept(2) load distribution in a multi-threaded server to be improved by using a distinct listener socket for each thread. This provides improved load distribution as compared to traditional techniques such using a single accept(2)ing thread that distributes connections, or having multiple threads that compete to accept(2) from the same socket.

For UDP sockets, the use of this option can provide better distribution of incoming datagrams to multiple processes (or threads) as compared to the traditional technique of having multiple processes compete to receive datagrams on the same socket.

    
por 27.01.2018 / 15:24