2012-03-01 249 views
0

我知道有可能将多个数据包堆叠到要读取的缓冲区,并且长数据包可能需要多次发送尝试循环才能完全发送。但是我对这些案件有关包装的问题:发送和接收套接字(TCP/IP)

  1. 如果我打电话的recv(或任何其他(低电平)函数),当有多个数据包等待被读取,将它归还所有堆叠进入我的缓冲区或只有其中一个(或者如果我的缓冲区不足,则是第一个的一部分)?
  2. 如果我发送一个需要多次迭代才能完全发送的长包,它会算作单个包还是多个包?这基本上是一个问题,它是否表示包裹发送不完整?

当我想到网络套接字封装时,我想到了这些问题。特殊字符用于标记数据包的开始和结束,这种分类导致无法分离多个数据包。

P.S.所有的问题都是关于TCP/IP的,但欢迎您分享有关UDP的信息(答案)。

回答

2

TCP套接字是基于流的。顺序是有保证的,但每次recv/read时收到的字节数可能是来自发送方的任何待处理字节块。您可以通过添加成帧信息来指定应将有效负载分块成消息的方式,从而在TCP基础上对基于消息的传输进行分层。这是WebSockets所做的。每个WebSocket消息/帧以至少2个字节的头部信息开始,其中包含要遵循的有效载荷的长度。这允许接收机等待并重新组装完整的消息。

例如,实现标准Websocket API或类似API(例如浏览器)的库/接口,onmessage事件将针对接收到的每个消息触发一次,并且事件的数据属性将包含整个消息。

请注意,在较早的Hixie版本的WebSockets中,每个帧都以'\ x00'开头并以'\ xff'结尾。当前标准化的IETF 6455(HyBi)协议版本使用头部信息,其中包含允许更容易处理帧的长度(但要注意,旧的和新的仍然基于消息并且具有基本相同的API)。

1

TCP连接提供字节流,所以请按照这样处理。没有应用程序消息边界被保留 - 一个发送可以对应于多个接收并且相反。你需要双方循环。

另一方面,UDP是基于数据报(即消息)的。在这里,一个读取将始终将单个数据报出列(除非您在套接字上混淆了低级标记)。事件如果您的应用程序缓冲区小于未决的数据报,并且只读取其中的一部分,则其余部分将丢失。解决这个问题的方法是将你发送的数据报的大小限制在正常MTU 1500(低IP和UDP头,实际上是1472)。