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を使用して複数のクライアントを接続しようとします。

Bastionが最初で、すべてがうまくいきます。

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

ただし、最初の接続の後にはいくつかの接続があり、それを所有しているプロセスとその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

3番目:

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がゼロになるのはなぜですか?何が起こっているのかを説明できる人はいますか?

答え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)で使用されます。リスニングソケットの保留中の接続キューから最初の接続要求を取得します。靴下、関連付けられた新しいソケットを作成し、ソケットを参照する新しいファイル記述子を返します。新しく作成されたソケットはリスニング状態ではありません。オリジナルソケット靴下この呼び出しの影響を受けません。

参照ソースman 7 socket:

SO_REUSEPORT(Linux 3.9以降)

複数のAF_INETまたはAF_INET6ソケットを同じソケットアドレスにバインドできます。このオプションは、呼び出す前にすべてのソケット(最初のソケットを含む)に設定する必要があります。バインディング(2)ソケットに。ポートのハイジャックを回避するには、同じアドレスにバインドされているすべてのプロセスに同じ有効なUIDが必要です。このオプションはTCPおよびUDPソケットに使用できます。

TCPソケットの場合、このオプションを使用すると承諾(2)マルチスレッドサーバーの負荷分散は、スレッドごとに異なるリスナーソケットを使用して強化できます。これにより、単一のaccept(2)スレッドを使用して接続を分散したり、複数のスレッドを使用して競合したりするなど、従来の技術よりも負荷分散が向上します。承諾(2)同じアウトレットで。

UDPソケットの場合、このオプションを使用すると、複数のプロセスが同じソケットからデータグラムを受信するために競合する従来の技術よりも、複数のプロセス(またはスレッド)に入ってくるデータグラムをより効果的に配布できます。

関連情報