【问题标题】:Sending And Receiving Sockets (TCP/IP)发送和接收套接字 (TCP/IP)
【发布时间】:2012-03-02 06:09:59
【问题描述】:

我知道多个数据包可能会堆叠到缓冲区中以进行读取,并且长数据包可能需要循环多次发送尝试才能完全发送。但我对这些情况下的包装有疑问:

  1. 如果我在有多个数据包等待读取时调用 recv(或任何替代(低级)函数),它会将它们全部返回到我的缓冲区中还是仅返回其中一个(如果我的缓冲区不足,还是第一个的一部分)?
  2. 如果我发送一个需要多次迭代才能完全发送的长数据包,它算作单个数据包还是多个数据包?基本上是一个问题,它是否标志着发送的包裹未满?

当我想到 Web 套接字打包时,我想到了这些问题。特殊字符用于标记数据包的开始和结束,这可能会导致无法分隔多个包的结论。

附:所有问题都与 TCP/IP 有关,但也欢迎您分享有关 UDP 的信息(答案)。

【问题讨论】:

    标签: sockets tcp websocket


    【解决方案1】:

    TCP 套接字是基于流的。顺序是有保证的,但每次接收/读取的字节数可以是来自发送方的任何未决字节块。您可以在 TCP 之上添加基于消息的传输层,方法是添加帧信息以指示应将有效负载分块为消息的方式。这就是 WebSockets 所做的。每个 WebSocket 消息/帧以至少 2 个字节的标头信息开头,其中包含要跟随的有效负载的长度。这允许接收者等待并重新组装完整的消息。

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

    请注意,在较旧的 Hixie 版本的 WebSockets 中,每个帧都以“\x00”开始并以“\xff”结束。当前标准化的 IETF 6455 (HyBi) 协议版本使用包含长度的标头信息,这样可以更轻松地处理帧(但请注意,旧的和新的仍然是基于消息的,并且具有基本相同的 API)。

    【讨论】:

      【解决方案2】:

      TCP 连接提供字节流,所以这样对待它。不保留应用程序消息边界 - 一个发送可以对应多个接收,反之亦然。两边都需要循环。

      另一方面,UDP 是基于数据报(即消息)的。在这里,一次读取将始终使单个数据报出队(除非您弄乱了套接字上的低级标志)。如果您的应用程序缓冲区小于待处理的数据报,并且您只读取其中的一部分,则其余部分将丢失。解决方法是将您发送的数据报的大小限制为低于 1500 的正常 MTU(更少的 IP 和 UDP 标头,因此实际上是 1472)。

      【讨论】:

        猜你喜欢
        • 2019-05-07
        • 2016-05-09
        • 2011-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-24
        • 1970-01-01
        • 2011-09-20
        相关资源
        最近更新 更多