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 ?有人可以解釋一下發生了什麼嗎?
伺服器程式碼只呼叫
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
:accept(sockfd)系統呼叫與基於連接的套接字類型(SOCK_STREAM、SOCK_SEQPACKET)一起使用。它為偵聽套接字sockfd提取掛起連接隊列中的第一個連接請求,創建一個新的連接套接字,並返回一個引用該套接字的新文件描述符。新創建的套接字不處於監聽狀態。原始套接字sockfd不受此呼叫的影響。
參考來自
man 7 socket
:SO_REUSEPORT(自 Linux 3.9 起)
允許將多個 AF_INET 或 AF_INET6 套接字綁定到相同的套接字地址。*在對套接字呼叫bind(2)*之前,必須在每個套接字(包括第一個套接字)上設置此選項。為防止埠劫持,綁定到同一地址的所有程序必須具有相同的有效 UID。此選項可用於 TCP 和 UDP 套接字。
對於 TCP 套接字,此選項允許通過為每個執行緒使用不同的偵聽器套接字來改進多執行緒伺服器中的accept(2)負載分配。與傳統技術相比,這提供了改進的負載分配,例如使用單個 accept(2)ing 執行緒來分配連接,或者讓多個執行緒競爭來自同一個套接字的accept(2) 。
對於 UDP 套接字,與讓多個程序競爭在同一個套接字上接收數據報的傳統技術相比,使用此選項可以更好地將傳入數據報分配給多個程序(或執行緒)。