从套接字读取一个字节与多个字节

时间:2016-05-26 11:28:55

标签: c++ c sockets unix

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

一次只读一个字节是个好主意吗?最大长度是4096.我知道从插座读取应该尽可能大,以便阅读,但在我的情况下,当最大长度不长时,这是一个很好的解决方案吗?

这种阅读有什么后果?

缓冲区溢出?

2 个答案:

答案 0 :(得分:3)

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

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

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

解决您的困境的方法是使用缓冲IO。创建或使用预先存在的适配器,该适配器将执行大read个以将数据导入用户空间缓冲区,然后您可以在最佳的任何块大小套件中从此缓冲区中选择字节。 / p>

答案 1 :(得分:0)

  

一次只读一个字节是个好主意吗?最大长度为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);