【问题标题】:What happends when a call to `send` fails when there is pending data from calls to `send` with `MSG_MORE`?当使用 `MSG_MORE` 调用 `send` 有待处理的数据时,调用 `send` 失败会发生什么?
【发布时间】:2017-10-22 14:04:39
【问题描述】:

来自man 2 send

MSG_MORE(自 Linux 2.4.4 起)

(…)

从 Linux 2.6 开始,UDP 套接字也支持此标志,并通知内核将在调用中发送的所有数据打包到设置此标志的单个数据报中,该数据报仅在执行未指定的调用时传输这个标志。

足够好。所以当我: 1) 向send() 发出几个调用,并指定标志MSG_MORE; 2) 在没有指定此标志的情况下向send() 发出调用并且send() 失败; 3) 再次拨打send()

调用 (1) 和 (3) 中的数据是否会合并到一个数据报中?

换句话说:对send() 的调用失败算作未能将此部分附加到整个数据报,还是算作未能将包含此调用的整个数据报发送到send()以及之前使用MSG_MOREsend() 的任何调用?

我希望是后者,因为我担心在某些情况下错误恢复可能会很困难。

【问题讨论】:

    标签: c linux sockets error-handling udp


    【解决方案1】:

    手册页遗漏了一条关键信息:在步骤 (2) 中“发送”的数据将进入在步骤 (1) 中累积的同一个数据报。只有这样,整个数据报才会真正被发送出去。不管这个实际的send是成功还是失败,数据报都已经消失了,并且(3)不可能与之连接。

    【讨论】:

      【解决方案2】:

      MSG_MORE 标志本质上意味着追加而不发送,调用者有更多数据要发送。一旦确定datagram 准备好实际发送,send() 会在没有MSG_MORE 的情况下被调用,并且带有所有附加的datagram 会被发送。但是如果发生错误,任何一直在增长的数据报都将不复存在。

      char msgs[][20] = {"msg1", "message2","more messages", "yet another message"};
      
      //scenario1 normal, no errors
      send(s, msgs[0], strlen(msgs[0]+1,MSG_MORE);//datagram is started 
      send(s, msgs[1], strlen(msgs[1]+1,MSG_MORE);//datagram is appended 
      send(s, msgs[2], strlen(msgs[2]+1,MSG_MORE);//datagram is appended 
      send(s, msgs[3], strlen(msgs[3]+1,0);//dategram is appended and sent 
      
      //scenario2, with errors
      send(s, msgs[0], strlen(msgs[0]+1,MSG_MORE);//datagram is started 
      send(s, msgs[1], strlen(msgs[1]+1,0);//dategram is appended  and send
      send(s, msgs[2], strlen(msgs[2]+1,MSG_MORE);//error occurs, datagram lost. 
      send(s, msgs[3], strlen(msgs[3]+1,0);//dategram is sent, but only `msgs[3]` 
      
      //scenario3 with errors at end
      send(s, msgs[0], strlen(msgs[0]+1,MSG_MORE);//datagram is started 
      send(s, msgs[1], strlen(msgs[1]+1,MSG_MORE);//datagram is appended
      send(s, msgs[2], strlen(msgs[2]+1,MSG_MORE);//datagram is appended 
      send(s, msgs[3], strlen(msgs[3]+1,0);//error occurs here, datagram lost.
      

      这就是无网走钢丝的危险。网络的一种可能性是在您调用send/MSG_MORE 命令时将消息并行附加到缓冲区。保留它,直到您成功发送您的datagram。如果失败,将缓冲区打包并重新发送(不带MSG_MORE)。

      【讨论】:

        猜你喜欢
        • 2019-04-20
        • 2020-08-14
        • 2021-08-20
        • 1970-01-01
        • 2021-07-05
        • 1970-01-01
        • 2014-09-02
        • 2020-08-24
        • 1970-01-01
        相关资源
        最近更新 更多