带有截断消息的 Socat udp 客户端/服务器

带有截断消息的 Socat udp 客户端/服务器

使用 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 数据报。

相关内容