Linux

只有一個 TCP 套接字(通過 nc)能夠一次將數據發送到同一主機/埠

  • March 1, 2022

簡單的複制 - 在一個視窗中觀察頂部的程序,在另一個執行中:nc -lkp 10000 > /dev/null & ( head -50000000 /dev/urandom | nc -N 127.0.0.1 10000 ) & ( head -50000000 /dev/urandom | nc -N 127.0.0.1 10000 )

觀察到只有一個headnc程序正在積極使用 CPU。

將 strace 附加到head不活動的 - 看到它在寫入時停止,例如:

strace: Process 589084 attached
write(1, "\264\347\270\26\27\24'BRb^\353\302\36@\216\17V\210*n\252`\353\330\351\276\2\250\330\350\217"..., 4096^Cstrace: Process 589084 detached
<detached ...>

在不同的埠上設置兩個偵聽器 - 例如 10000 和 10001,並且都全速執行。

這是一個簡單的範例,但我可以使用其他輸入和輸出來重現它 - 例如,zcatting 大文件並通過網路將它們發送到生產服務。它與輸入無關,與偵聽套接字無關。

那麼 - 為什麼我只能有一個 tcp 連接到任何給定的主機/埠主動發送數據?

有一個獨立的數據源(如果你不相信我,請隨意嘗試)和一個獨立的程序打開它自己的 tcp 連接(netstat將顯示它們都打開) - 唯一的共同點是目的地(它沒有必須nc傾聽lo- 發生任何事情)。

鑑於目的地肯定可以有多個傳入套接字一次接收數據,而源肯定可以一次將數據發送到多個網路套接字,我正在努力找出爭用的來源,導致只有一個管道處於活動狀態一次。

免責聲明:有很多nc變體。假設-k它是 OpenBSD 變體。每個nc變體都有自己的特權。

nc是這項工作的錯誤工具:nc -lkp 10000將同時管理一個連接,因為它不會分叉,並且儘管在第一個處理完成之前poll(2)從不使用accept(2)第二個傳入連接:它保證第二個連接將是未處理。如果還有更多,它們將開始保持SYN-SENT狀態,因為nc -lkp 10000使用 1 作為listen(2)積壓:這不是隨機選擇。這可以通過strace在正在執行的nc -lkp 10000程序上使用來檢查。

關於-k選項的文件也有同樣的說法:

-k

當一個連接完成後,監聽另一個。需要-l.

$$ … $$

它的編寫方式並不表明將同時接受兩個連接:只有一個落後於前一個。


將監聽的netcat替換為socat(-d -d以獲取更多資訊):

socat -d -d tcp4-listen:10000,reuseaddr,fork /dev/null

fork選項可確保輕鬆進行並行處理:每個連接一個程序。

引用自:https://serverfault.com/questions/1095026