【问题标题】:Reading one byte vs multiple bytes from a socket从套接字读取一个字节与多个字节
【发布时间】:2016-09-24 09:11:26
【问题描述】:

我必须从套接字读取长度未知的数据。我需要等待特定的字符序列停止阅读。

一次只读取一个字节是个好主意吗?最大长度为 4096。我知道从套接字读取应该实现尽可能大的读取大小,但在我的情况下,当最大长度不长时,这是一个好的解决方案吗?

这样阅读的后果是什么?

缓冲区溢出?

【问题讨论】:

  • “一次只读取一个字节是个好主意吗?” 很可能不是。使用select()poll() 循环并解除阻塞read(),一次读取尽可能多的可用字节并放入缓冲区。

标签: c++ c sockets unix


【解决方案1】:

首先,答案很大程度上取决于套接字的类型。

如果这是一个数据报套接字 (UDP),那么答案是响亮的。从数据报套接字中仅读取一个字节会导致您丢失重要信息。读取的大小应该(至少)对应于发送的大小。

假设这是一个蒸汽套接字 (TCP),一次只读取一个字节不会造成语义损害。无论哪种方式,结果都是正确的。这并不是说这是一个好主意。每次调用read 都需要切换到内核模式并执行一系列操作。无论您是检索一个字节的批次,这些成本同样高。因此,在性能方面,强烈建议您每次执行更大的读取。

解决您的困境的方法是使用缓冲 IO。创建或使用预先存在的适配器,该适配器将执行大型 reads 以将数据放入用户空间缓冲区,然后您可以从该缓冲区中选择最适合您的块大小的字节。

【讨论】:

    【解决方案2】:

    一次只读取一个字节是个好主意吗?最大长度为 4096

    不,这不是一个好主意,尤其是在使用阻塞 read() 时。


    您可以使用具有固定大小的本地缓冲区,以便读取最大数据:

     std::array<uint8_t,4096> buffer;
    

    并使用read()的返回值实际有多少数据可用

     std::vector<uint8_t> message;
    
     int bytes_read = 0;
     do {
         bytes_read = read(sockfd,buffer.data(),buffer.size());
         if(bytes_read >= 0) {
              // inspect the received data for the stop sequence
              if( /* stop sequence detected */ ) {
                  break;
              }
              // collect data
              message.insert(message.end(),&buffer.begin(),&buffer[bytes_read]);
         }
     } while(bytes_read > 0);
    

    【讨论】:

      猜你喜欢
      • 2010-10-30
      • 1970-01-01
      • 2020-10-20
      • 1970-01-01
      • 2015-09-01
      • 2012-07-15
      • 1970-01-01
      • 1970-01-01
      • 2012-10-25
      相关资源
      最近更新 更多