WSASend 是不是将所有 WSABUF 缓冲区作为单个数据包发送?

Posted

技术标签:

【中文标题】WSASend 是不是将所有 WSABUF 缓冲区作为单个数据包发送?【英文标题】:Does WSASend send all WSABUF buffers as a single packet?WSASend 是否将所有 WSABUF 缓冲区作为单个数据包发送? 【发布时间】:2013-12-01 15:35:42 【问题描述】:

标题可能最能说明问题。

无论如何,我有一个从另一个源接收的数据缓冲区,我想在一个包含序列号(作为第一个字节)的单个 UDP 数据包中发送它 -> 我想将序列号添加到给定的缓冲!

我不想分配一个新的缓冲区,而是将其大小设置为 size+4,将序列号设置为第一个字节并将数据复制到缓冲区中,我想只使用 WSA 的分散收集机制。

遗憾的是,没有 WSA 文档明确指定 WSASend 保证所有缓冲区都将发送一个数据包(数据包大小将保持为

我可以确定它会以这种方式工作吗?还是我应该重新构建数据包?

最好, 丹尼尔

【问题讨论】:

如果 UDP 可以对消息进行分段,那么就不可能接收它们,因为它们可能会完全乱码。 @usr:但是 UDP(或者更确切地说是 IP)可以分段消息。最好不要这样做,因为它会放大丢包的影响,但它肯定是可能的。 UDP 可以并且将使用 1500 字节(或类似大小)的片段发送最多 65535-40 字节的任何数据报。 您永远不会从您的操作系统收到部分 UDP 消息。如果这是可能的,那么所有内容最终都可能会出现乱码,因为后面的片段可能会在更早的片段之后到达(因为 UDP 缺乏排序)。这将允许任何消息被打乱成任何可能的排列。不可能的。;我认为使用了 IP 分片,以便分片对 UDP 是透明的。不确定,没关系。操作系统保证您完整的 UDP 消息。 @usr 你错了。 UDP 数据包可以被 IP 层以正确的顺序分段和重组。每个片段都有足够的信息来做到这一点。在 UDP 中不会发生的是重新传输丢失的片段,这会导致整个数据报完全丢失。 @EJP 我并不是说它们没有碎片化和重组。这就是我要说的:碎片对于接收数据包的应用程序是透明的。您永远不会收到部分数据包。 【参考方案1】:

它以迂回的方式记录:

对于面向消息的套接字,不要超过底层提供者的最大消息大小,可以通过获取套接字选项 SO_MAX_MSG_SIZE 的值来获得。如果数据太长而无法以原子方式通过底层协议,则返回错误 WSAEMSGSIZE,并且不传输任何数据。

很明显,它将缓冲区中的数据组合成一个 UDP 数据包。如果没有,那么返回 WSAEMSGSIZE 错误就没有意义了。

【讨论】:

如果单个缓冲区超出大小,即使每个缓冲区都是新数据报,它也可能返回 WSAEMSGSIZE。 你说不,我说是,OP 会说好的。

以上是关于WSASend 是不是将所有 WSABUF 缓冲区作为单个数据包发送?的主要内容,如果未能解决你的问题,请参考以下文章

一个 IOCP 文档解释问题 - 缓冲区所有权模糊性

在重叠模式下使用 WSASend 时,我应该何时释放缓冲区?

wsasend lpnumberofbytesSent

我应该同时进行 WSASend() 调用吗?

如何避免使用函数调用 WSAsend 将多个缓冲区组合成一个 UDP 数据包?

IOCP 服务器并使用单个 wsasend 发送数据