sudo netstat -antp 不显示 PID

sudo netstat -antp 不显示 PID

我正在用套接字测试东西,我遇到了奇怪的情况:

我用c编写了非常简单的tcp服务器,我在accept()之后将其阻止,只是为了看看同时接受多个连接尝试时会发生什么:

这是服务器代码的摘录:

//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);

当服务器要求用户输入一个整数时,我尝试使用 telnet 连接多个客户端。

堡垒第一个,一切都好:

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

但在第一个之后,即使我是 root,也有一些连接我看不到拥有它的进程及其 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

第三个:

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

几天后,我再次尝试使用 netstat -antpe 作为 root,这就是我得到的结果:

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

为什么进程或连接的 inode 可以为 0 ?有人可以解释一下发生了什么事吗?

答案1

服务器代码accept()仅调用一次。因此,只有第一次连接尝试被有效地接受,其余的客户端连接保留在内核空间中的连接请求队列中。当accept()再次调用时,将从队列中检索下一个客户端连接。

当客户端连接保留在内核空间中时,没有进程拥有客户端连接,因为如果多个进程或线程在所有参与套接字描述符上启用选项,则它们可以合法地接受来自唯一地址和端口对的连接SO_REUSEPORT

您可以SO_REUSEPORT通过在调用之前添加以下代码片段bind()并运行多个服务器来自行测试该选项。您会发现内核将在它们之间分配请求。

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

参考自man 2 accept

接受(sockfd)系统调用与基于连接的套接字类型(SOCK_STREAM、SOCK_SEQPACKET)一起使用。它提取侦听套接字的挂起连接队列上的第一个连接请求,sockfd,创建一个新的已连接套接字,并返回引用该套接字的新文件描述符。新创建的socket不处于监听状态。原来的插座sockfd不受此调用的影响。

参考自man 7 socket

SO_REUSEPORT(自 Linux 3.9 起)

允许将多个 AF_INET 或 AF_INET6 套接字绑定到相同的套接字地址。在调用之前必须在每个套接字(包括第一个套接字)上设置此选项绑定(2)在插座上。为了防止端口劫持,绑定到同一地址的所有进程必须具有相同的有效 UID。此选项可用于 TCP 和 UDP 套接字。

对于 TCP 套接字,此选项允许接受(2)通过为每个线程使用不同的侦听器套接字,可以改善多线程服务器中的负载分配。与传统技术相比,这提供了改进的负载分配,例如使用单个接受(2)线程来分配连接,或者使用多个线程来竞争接受(2)来自同一个插座。

对于 UDP 套接字,与让多个进程竞争在同一套接字上接收数据报的传统技术相比,使用此选项可以更好地将传入数据报分发到多个进程(或线程)。

相关内容