使用Boost::asio::async_read进行第一次读取时的EOF
EOF on first read with Boost::asio::async_read
我正在使用Boost Asio实现一个非常简单的协议。我发送一个简单的查询,并得到一个可变长度的响应。异步发送似乎起作用,并调用写处理程序。因为我不知道响应有多长,所以我从读取固定的8字节头开始。它总是存在的,它包含了余数的长度。相关电话:
char input[256]; // Large enough to also hold the variable part.
async_read(socket, buffer(input), transfer_at_least(8), callback);
在callback
中,我得到一个表示"文件结束"的boost::system::error_code
。果然,套接字不再打开。但它是一个TCP套接字。在输入结束时失败并关闭套接字的意义是什么?会有更多的输入。我知道远程端没有关闭套接字,这是已知正确实现此协议的生产代码。
异步读的全部原因当然是为了不阻塞等待响应。那么我如何在前8个字节之后获得回调,而不关闭Asio对我的套接字?
现有的问题是相似的,但不同:要么他们不使用异步读取,要么他们不做固定大小的读取,或者他们只有在第一次读取后才有问题,或者他们有io_service::run
问题(我不,它在EOF错误发生后按预期返回)
End of file (boost::asio::error::eof
)表示对端已关闭连接。它并不表示流没有更多的数据可读。的提振。Asio streams文档说明:
流的结束可能导致
read
、async_read
、read_until
或async_read_until
函数违反它们的契约。例如,N
字节的读取可能会因为EOF
而提前完成。
虽然这个错误可能是由于未定义的行为而发生的。提振。Asio要求提供给async_read()
(input
)的缓冲区必须保持有效,直到处理器(callback
)被调用。
同样,如果套接字已经在本地关闭,那么操作的错误将是boost::asio::error::operation_aborted
。
下面是一个基本的应用程序,可以用来演示这种行为:
#include <boost/array.hpp>
#include <boost/asio.hpp>
void on_read(
const boost::system::error_code& error,
std::size_t bytes_transferred)
{
std::cout << "read " << bytes_transferred << " bytes with "
<< error.message() << std::endl;
}
int main(int argc, char* argv[])
{
if (argc != 2)
{
std::cerr << "Usage: <port>n";
return 1;
}
// Create socket and connet to local port.
namespace ip = boost::asio::ip;
boost::asio::io_service io_service;
ip::tcp::socket socket(io_service);
socket.connect(ip::tcp::endpoint(
ip::address::from_string("127.0.0.1"), std::atoi(argv[1])));
// Start read operation.
boost::array<char, 512> buffer;
async_read(socket,
boost::asio::buffer(buffer),
boost::asio::transfer_at_least(7),
&on_read);
// Run the service.
io_service.run();
}
下面演示向TCP连接写入两次。第一次写入足够小,客户端将在下一次写入之前读取所有流的数据。
<>之前$ nc -l 12345 &[1] 11709美元/。输出12345 &[2] 11712$ fg 1Nc -l 12345你好输入世界输入读取12字节成功之前相同的程序,但连接被显式终止:
<>之前$ nc -l 12345 &[1] 11773美元/。输出12345 &[2] 11775$ fg 1Nc -l 12345你好输入世界 ctrl - c 读取6字节与文件结束原来是协议实现中的竞争条件。如果未接受初始消息,则远程端关闭套接字。在发送初始消息后,当地确实对此进行了检查。然而,在转到异步操作之后,套接字检查是在本地返回异步写操作之后和异步读操作之前完成的。
没有办法准确地预测远程端何时关闭套接字,你不能等待。您唯一知道的是,如果您收到这8个字节,它不会关闭套接字。因此,异步读取时的EOF结果是我必须处理的。
我怀疑现有的(同步)代码可能有类似的时间问题,但尚未浮出水面:(
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 蓝牙插座只能读取一次,为什么?
- 我必须构建我的项目 2 次,第一次失败,因为它无法打开库
- 是什么导致我的循环在第一次迭代中运行得更慢
- QLibrary 函数在第一次调用时工作缓慢
- 第一次尝试使用new动态创建结构数组,程序挂起没有错误
- 为什么第一次迭代后的指针指向随机值?
- 如何防止GUI挂起,同时允许第二次操作与Qt中的第一次操作一起执行
- LAPACK函数在第一次迭代后变慢
- 为什么 Boost unordered_map 在第一次插入时需要太多时间?
- EGL 在第一次 opengl 函数调用时崩溃
- 提升 Asio SSL 无法第二次接收数据(第一次确定)
- 数组仅在第一次返回错误值
- C++程序在第一次尝试时会给出垃圾,但如果它捕获异常并重试,则会给出适当的值
- 为什么字符串的长度在第一次读取文件时相差 1?
- Qt读取访问在以下位置发生冲突:0x0,标志=0x0(第一次机会)
- 在0x5919c8ec (msvcr100d.dll)的第一次机会异常:0xC0000005:访问违反读取位置0xfee
- 读取UDP套接字两次,在第一次调用后丢弃剩余字节
- 接收在第一次读取之前被发送到串口的数据
- 使用Boost::asio::async_read进行第一次读取时的EOF