【发布时间】:2021-03-15 21:53:17
【问题描述】:
我对套接字的长期理解是不能依赖对 recv() 的调用来返回请求的数据量(无论是否阻塞套接字)
我试图通过在一次呼叫中发送大量 (1mb) 数据来向同事证明这一点,以便发送(从我家,通过有效的 VPN 网络到他家 - 涉及多个路由器 wifi 等)
套接字被阻塞了,所以我不希望 send() 返回任何内容,只返回 1mb 并一次性完成,但我确实希望 recv() 调用返回小于 1mb,即使套接字阻塞。
这个测试的背景是说服他我们需要在消息协议中的长度和有效负载,以便您知道消息从哪里开始/结束,并且您不能依赖一个 recv() 调用返回一条消息。如果我们确实有这个协议,为了向他展示一个简单的 recv() 甚至是不够的,我们需要在一个循环中进行 recv(),即使是 4 字节的消息长度字段,以防 recv() 不返回请求的大小。
我对 TCP 通信的理解有误吗?这些年来我是不是一直在做这件事?如果不是,我如何强制这些 recv() 碎片化?
【问题讨论】:
-
我很惊讶您一次收到所有 1MB。这可能是在从
recv()调用返回之前缓冲了数百个数据包。尝试使用 10MB,甚至 100MB。 -
这就是我的想法!,1mb,没有拆分,不太可能。我开始怀疑它是否是 VPN 软件,因此它与我们之间有多少种网络无关,VPN S/W 是否有效地允许在另一端重构无限大小的 TCP 数据包?也许我在家里尝试通过 wifi 连接两台笔记本电脑?
-
对,所以我做了一个 noddy 应用程序,每秒发送 16k 次心跳,并且完全通过家里的 wifi 完成。走到房子外面,HB 停止了,我没有一次收到部分 recv(),它暂停了,但是当我回到范围内时继续
-
所以我没有提到,我们使用 SSL 进行连接,但是我们在 SSL 和非 SSL 上都做了很多测试。我上面的 noddy 16k 测试是在 SSL 上完成的(C# SslStream 包装 TCPClient.GetStream)。如果我的阅读器在发出阅读之前等待 5 秒链接,并且我确保我的发件人在那段时间内发送 2 条不同的消息,接收者将获得 2 次阅读!!!!!!但是,如果我切换到非 ssl(使用 Client.GetStream 或 Client.Client),那么阅读器会在 1 次读取中获得两条消息。我将在非 ssl 上重复户外步行测试
-
走到wifi连接的边缘我不能强制recv在非ssl套接字上进行部分读取。我是不是把头靠在墙上试图“强迫”这种分裂状态?