使用nodejs我可以傳輸負載為50000個字元的udp資料包。但我無法使用socat(客戶端和伺服器上的Linux ubuntu 20.04)來做到這一點。
對於此測試,我一直使用 VPN 將我的家庭主機連接到我的工作主機。我本來以為 socat 會遺失一些數據,但沒有到那個程度!
在遠端(工作)主機上,socat 伺服器等待請求傳回超過 50000 位元組的臃腫 udp 回應。
cat <<EOF > sotest.sh
#!/bin/bash
head -c 50000 < /dev/zero | tr '\0' 'q'
EOF
chmod +x sotest.sh
socat udp4-listen:13000,reuseaddr,fork EXEC:"./sotest.sh" # server
#client
printf "trigger" |socat -T 5 -,ignoreeof udp4:10.50.1.184:13000,sndbuf=64000,rcvbuf=64000 > t.t
檢查訊息大小wc -c t.t
給我大約 8k 字元而不是 50k。
如果我使用我的nodejs udp客戶端/伺服器,則伺服器發送的50k字元訊息將被nodejs客戶端完整接收。客戶 :https://jsfiddle.net/xtcpL63a/ 伺服器:https://jsfiddle.net/851fc7bp/
我唯一的線索是 socat 的錯誤訊息,只能在調試模式下看到
022/12/03 22:37:40 socat[1051733] N forked off child process 1051734
2022/12/03 22:37:40 socat[1051733] N forked off child process 1051734
2022/12/03 22:37:40 socat[1051733] I close(7)
2022/12/03 22:37:40 socat[1051733] I resolved and opened all sock addresses
2022/12/03 22:37:40 socat[1051733] N starting data transfer loop with FDs [5,5] and [6,6]
2022/12/03 22:37:40 socat[1051733] I transferred 73 bytes from 5 to 6
2022/12/03 22:37:40 socat[1051734] I just born: child process 1051734
2022/12/03 22:37:40 socat[1051734] I close(4)
2022/12/03 22:37:40 socat[1051734] I close(3)
2022/12/03 22:37:40 socat[1051734] I close(6)
2022/12/03 22:37:40 socat[1051734] I dup2(7, 0) -> 0
2022/12/03 22:37:40 socat[1051734] I dup2(7, 1) -> 1
2022/12/03 22:37:40 socat[1051734] I close(7)
2022/12/03 22:37:40 socat[1051734] N execvp'ing "./sotest.sh"
2022/12/03 22:37:40 socat[1051733] I transferred 8192 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] I transferred 8192 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] I transferred 8192 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] I transferred 8192 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] I transferred 8192 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] I transferred 8192 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] I transferred 848 bytes from 6 to 5
2022/12/03 22:37:40 socat[1051733] E read(5, 0x5566b4417150, 8192): Connection refused
2022/12/03 22:37:40 socat[1051733] N exit(1)
2022/12/03 22:37:40 socat[1051733] I shutdown(5, 2)
2022/12/03 22:37:40 socat[1051733] I shutdown(6, 2)
這個問題與 Linux 端的緩衝區無關,也與 mtu 無關。那麼 socat 發生了什麼事?
解決方案:Tero Kilkanen 指出了問題。強制 socat 在客戶端使用更大的緩衝區使我能夠完整地接收訊息;它解決了但並沒有真正解釋這種行為...
#client
printf "${MSG}" |socat -b100000 -T 5 -,ignoreeof udp4:10.50.1.184:13000,sndbuf=64000,rcvbuf=64000 > t.t
在伺服器端,它確保發送一個資料包;您可以在調試日誌中看到行為的差異:
socat -b100000 -d -d -d udp4-listen:13000,reuseaddr,fork EXEC:"./sotest.sh"
答案1
socat
預設緩衝區大小為 8k。您只需在客戶端設定緩衝區大小。因此伺服器使用預設的 8k 緩衝區大小。這就是為什麼資料包以 8k UDP 資料報的形式發送。
然後由於某種原因客戶端只讀取伺服器發送的第一個UDP資料報。