对原始套接字的读取是否可以一次返回多个数据包?

时间:2013-10-06 11:53:46

标签: c++ sockets boost

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

更具体地说,情况是:

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

2 个答案:

答案 0 :(得分:2)

Boost basic_raw_socket::async_receive不支持接收原始套接字,它只适用于已连接的套接字,而且无法连接到原始套接字 - 您需要basic_raw_socket::async_receive_from。此函数显式支持接收到多个缓冲区,因此您无法保证一次只能获得零个或一个数据报。

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

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

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

<小时/> 1 分散/收集豁免

答案 1 :(得分:1)

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

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