2016-05-26 162 views
0

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

一次只读取一个字节是好主意吗?最大长度是4096.我知道从套接字读取应该尽可能大的尺寸来读取,但在我的情况下,当最大长度不长时,它是很好的解决方案吗?

这样的阅读有什么后果?

缓冲区溢出?

+0

_“一次只读取一个字节是否好主意?”_最可能的不是。使用'select()'或'poll()'循环和unblocking'read()',读取一次可用的字节并放入缓冲区。 –

回答

2

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

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

假设这是一个蒸汽插座(TCP),一次只读一个字节没有语义伤害。结果无论如何都是正确的。这并不是说这是个好主意。每次调用read都需要切换到内核模式并执行一堆操作。无论您是检索一个字节的批量,这些代价都是相当昂贵的。因此,强烈建议您在性能方面每次执行较大的读取操作。

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

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);