boost asio async_read_some 只读数据
Posted
技术标签:
【中文标题】boost asio async_read_some 只读数据【英文标题】:boost asio async_read_some reading only pieces of data 【发布时间】:2012-06-18 13:48:58 【问题描述】:我有一个使用 boost::asio 进行读/写操作的 c++ 服务器 - 写出消息工作正常 - 但由于某种原因我无法让读取工作
我从客户端发送给它的消息是 15 条 16 位无符号短裤 - 我的测试消息是这样的:
1, 34, 7, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0
现在在服务器上,我经常看到这样的事情。读取通常被分解和/或乘以 256
这是一次发送两次
reading length = 8: [1 34 7 0 0 0 0 0]
reading length = 3: [1024 0 0]
reading length = 3: [0 0 0]
reading length = 8: [1 34 7 0 0 0 0 0]
reading length = 6: [1024 0 0 0 0 0]
这是第二次发送两次
reading length = 8: [1 34 7 0 0 0 0 0]
reading length = 6: [1024 0 0 0 0 0]
reading length = 6: [1 34 7 0 0 0]
reading length = 1: [0]
reading length = 0: []
reading length = 0: []
reading length = 2: [0 0]
reading length = 2: [0 0]
reading length = 1: [0]
这是第三次发送一次(我不知道这里发生了什么)
reading length = 14: [256 8704 1792 0 0 0 0 0 1024 0 0 0 0 0]
这是实际的服务器读取代码
void Session::start(void)
msg_interface->add_msg_listener(this);
_socket.async_read_some(
boost::asio::buffer(_read_data_buffer, READ_DATA_BUFFER_LENGTH),
boost::bind(&Session::handle_read, this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
void Session::handle_read(const boost::system::error_code& error, std::size_t bytes_transferred)
if (error)
msg_interface->remove_msg_listener(this);
delete this;
else
if (bytes_transferred != 0)
// print what we've received
const int length = bytes_transferred / sizeof(uint16_t);
std::cout << "reading length = " << length << ": [";
for (int i = 0; i < length; i++)
const uint16_t data = ntohs(_read_data_buffer[i]);
std::cout << data;
if (i != length - 1)
std::cout << " ";
std::cout << "]" << std::endl;
_socket.async_read_some(
boost::asio::buffer(_read_data_buffer, READ_DATA_BUFFER_LENGTH),
boost::bind(&Session::handle_read, this, boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
变量如下
const int READ_DATA_BUFFER_LENGTH = 1024;
class AbstractSession
protected:
uint16_t _read_data_buffer[READ_DATA_BUFFER_LENGTH];
...
有一件事 - 我使用相同的 IO 服务在收到消息时写入消息(服务器正在与旧接口通信并将收到的消息发送给所有客户端)并从客户端读取消息.可以为两者使用相同的 io 服务导致这种情况发生吗?
有什么想法可以解决这个问题吗?
【问题讨论】:
删除这个 - 在 handle_read 中是错误的。 【参考方案1】:您的代码完成了它应该做的事情 - 它尽可能多地读取数据。这就是函数async_read_some
名称以“some”结尾的原因——它读取“some”字节并且不承诺做更多的事情。文档还说:
如果您需要确保 在异步操作之前读取请求的数据量 完成。
这似乎是你的情况,除非你重新设计你的接收器来处理部分读取。
【讨论】:
好吧 - 我想我想知道什么,我将需要阅读 3 条不同长度的输入消息 - 有什么理由它只阅读这样的一定数量而不是阅读完整的信息?另外 - 当我使用 async_read 时,它不会完全读取数据(14 而不是 15)然后消息变得不同步(正确读取的下一条消息的第一个字被附加到最后一条消息 - 下一条消息缺少第一个字)并且我永远不会收到正确的消息 - 我也在 localhost 上进行测试,所以我看不出它为什么会丢失数据 我还注意到,如果我每秒从客户端发送一次消息,它最终会同步并开始在服务器上正确读取 - 我真的很困惑为什么会发生这种情况 -然后每 28 或 30 条消息中出现一次,因此它只会将其乘以 256 @seanchriste:TCP/IP,尤其是非阻塞读/写超出了 cmets 的范围。我唯一能建议的就是买一些关于它的好书。您不应该能够发送或接收完整的消息,它是一个流协议... async_read 最终修复了它 - 我仍然很困惑为什么使用 async_read_some 会随机乘以它读取的数据(似乎它正在沿线某处移动位) - 但异步读取最终修复了那个问题 - 我没有看到任何订购问题,谢谢 没问题。异步读取一些不会增加任何东西。它从 OS TCP/IP 堆栈获取尽可能多的数据可供进程使用。有多少字节取决于 MTU 大小、另一部分实际发送数据的方式(即启用或禁用 nagle)等。在任何一种情况下,都不要将这些数字视为“神奇”数字 - 什么都不做。你所看到的就是你得到的。async_read
所做的只是获取这些数据块,直到它有足够的字节,然后将这些数据以一个块的形式传递给您。所以在引擎盖下它在技术上没有任何用处。只是简化您的生活。以上是关于boost asio async_read_some 只读数据的主要内容,如果未能解决你的问题,请参考以下文章
boost asio async_read_some 只读数据
为啥 boost asio async_read_some 在特定情况下不调用回调?