3

读取原始套接字时,它总是返回正好 0 或 1 个数据包吗?

更具体地说,情况是否如此:

  1. linux/win32 用户空间 API?
  2. boost::asio basic_raw_socket.async_receive()
4

2 回答 2

2

Boostbasic_raw_socket::async_receive不支持接收原始套接字,它只适用于连接的套接字,并且不能连接到原始套接字——你需要这样做basic_raw_socket::async_receive_from。此函数明确支持接收到多个缓冲区,因此您无法保证一次只能获得零个或一个数据报。

但是请注意,不能严格保证您将(或可以)一次接收多个数据报。这是库的 API 明确允许的(因为您可以提供多个缓冲区),但它没有说明库需要实际使用所有缓冲区。因此,即使您提供多个缓冲区,库在技术上也可能始终只返回一个数据报。如果您在“一个”异步接收操作中获得多个数据报,这可能会通过操作系统层上的多个读取操作来模拟(除非操作系统支持套接字上的分散/收集 I/O,并且这是在您平台的 Boost 版本中实现的)。

在套接字层,“原始”表示一个数据报套接字(没有原始流套接字之类的东西!),并且在数据报套接字上读取总是1返回一个完整的数据报(或它的一部分,如果提供的缓冲区太小,在这种情况下,其余部分被丢弃)或错误。在 Linux 和 Windows 以及所有其他平台上,这种行为是相同的,假设实现没有中断。
请注意,您通常需要管理权限才能在原始套接字上发送和接收,对于 Windows,您需要早期的、未打补丁的 Windows XP 或服务器版本(否则原始套接字被禁用以防止地址欺骗、伪造的 TCP 重置和其他攻击)。

为了澄清上述内容:原始套接字将接收“网络层”(第 3 级)数据报。即使这些数据包确实属于 TCP 流或者是 UDP 数据包,对于您的原始套接字,它们仍然只是 IP 数据包。因此,它们没有端口号(它们有,但作为有效载荷,而不是作为报头的一部分),没有任何东西可以连接,也没有其他信息,例如用于确定数据包在流中的位置的序列号. 因此,不存在非数据包原始套接字之类的东西,也没有任何东西可以连接。


1分散/聚集豁免

于 2013-10-06T21:08:54.353 回答
1

如果您使用数据报套接字(例如:原始数据包套接字或 UDP 套接字),那么您将得到正好 0(无)或 1 个数据包。

如果您使用面向连接的套接字(例如:TCP 套接字),那么您可以从任何 API 获取的消息数量与实际接收的数据包数量没有任何强制性关系。

于 2013-10-06T21:06:43.930 回答