C++11 boost asio async\u read no调用回调
我正在尝试异步读取大量数据 对于同步模式下的“其他”库,我需要按块调用读取多次,因为tcp是一个流,并且窗口大小是有限的 因此,我认为需要使用boost asio的C++11 boost asio async\u read no调用回调,c++11,asynchronous,tcp,network-programming,boost-asio,C++11,Asynchronous,Tcp,Network Programming,Boost Asio,我正在尝试异步读取大量数据 对于同步模式下的“其他”库,我需要按块调用读取多次,因为tcp是一个流,并且窗口大小是有限的 因此,我认为需要使用boost asio的async_read,但回调是针对短数据(例如:1024)调用的,当数据量增加时(例如:max_length=80000>65536),回调不被调用,那么我做错了什么?这是一个产生我的问题的示例: #include <cstdio> #include <thread> #include <boost/a
async_read
,但回调是针对短数据(例如:1024)调用的,当数据量增加时(例如:max_length=80000>65536
),回调不被调用,那么我做错了什么?这是一个产生我的问题的示例:
#include <cstdio>
#include <thread>
#include <boost/asio/io_service.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/ip/tcp.hpp>
namespace ba = boost::asio;
enum { max_length = 1024 };
int main() {
ba::io_service io_service;
ba::ip::tcp::socket sk(io_service);
ba::ip::tcp::resolver resolver(io_service);
ba::connect(sk,
resolver.resolve(ba::ip::tcp::resolver::query{ba::ip::tcp::v4(),
"127.0.0.1",
"8881"}));
char request[max_length];
ba::async_read(sk,
ba::buffer(request, max_length),
[](const boost::system::error_code& err, std::size_t){
if (!err) {
std::printf("Callback without error!\n");
} else {
std::fprintf(stderr, "Callback with error!\n");
}
});
io_service.run_one();
// wait the transtition in the async thread.
std::this_thread::sleep_for(std::chrono::milliseconds{1000});
return EXIT_SUCCESS;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
名称空间ba=boost::asio;
枚举{max_length=1024};
int main(){
ba::io_服务io_服务;
ba::ip::tcp::socket sk(io_服务);
ba::ip::tcp::解析器解析器(io_服务);
ba::连接(sk,
resolver.resolve(ba::ip::tcp::resolver::query{ba::ip::tcp::v4(),
"127.0.0.1",
"8881"}));
字符请求[最大长度];
ba::异步读取(sk,
ba::缓冲区(请求,最大长度),
[](const boost::system::error\u code&err,std::size\t){
如果(!err){
std::printf(“无错误回调!\n”);
}否则{
std::fprintf(stderr,“带错误的回调!\n”);
}
});
io_服务。运行_one();
//在异步线程中等待转换。
std::this_thread::sleep_for(std::chrono::毫秒{1000});
返回退出成功;
}
您正在使用的异步读取的重载相当于:
boost::asio::async_read(
s, buffers,
boost::asio::transfer_all(), // this is the completion condition
handler);
transfer\u all
条件意味着只有当缓冲区已满或连接结束时,传输才会完成
因此,如果没有看到调用回调,可能是因为连接未关闭(从另一端),或者缓冲区尚未满
还有其他完成条件,例如transfer\u至少
和transfer\u精确
,以及其他异步读取*
功能。如果不知道你想做什么,就很难推荐你需要的
您也可以调用套接字的async\u read\u some
方法,它的行为更像传统的低级别BSD套接字(只要读取某个内容,就会调用回调)。您正在使用的async\u read
的重载相当于:
boost::asio::async_read(
s, buffers,
boost::asio::transfer_all(), // this is the completion condition
handler);
transfer\u all
条件意味着只有当缓冲区已满或连接结束时,传输才会完成
因此,如果没有看到调用回调,可能是因为连接未关闭(从另一端),或者缓冲区尚未满
还有其他完成条件,例如transfer\u至少
和transfer\u精确
,以及其他异步读取*
功能。如果不知道你想做什么,就很难推荐你需要的
您还可以调用套接字的async\u read\u some
方法,它的行为更像传统的低级别BSD套接字(一旦读取了某个内容,就会调用回调)。这要感谢2015年2月24日的Antony Polukhin
尝试使用io_service.run();而不是io_服务。运行_one();。另外,修复错误检查:
// (err == boost::asio::error::eof) - Connection
// closed cleanly by peer
if (!err || err == ba::error::eof) {
std::printf("Callback without error!\n");
} else {
std::fprintf(stderr, "Callback with error!\n");
}
此外,看起来您不需要以下行:
std::this_thread::sleep_for(std::chrono::毫秒{1000})
简要说明:
async_read操作通过零次或多次调用流的async_read_some函数来实现。调用io_service.run_one()时,您请求只执行一个调用-第一个对异步\u read_some的调用(将跳过其他调用)。这就是为什么您只接收65535个字节,而不调用回调(回调将在最后一次异步读取完成后调用)
io_service.run()和io_service.run_one()在当前线程中运行操作并阻塞线程,直到操作完成,因此不需要调用sleep。 感谢2015年2月24日的Antony Polukhin
尝试使用io_service.run();而不是io_服务。运行_one();。另外,修复错误检查:
// (err == boost::asio::error::eof) - Connection
// closed cleanly by peer
if (!err || err == ba::error::eof) {
std::printf("Callback without error!\n");
} else {
std::fprintf(stderr, "Callback with error!\n");
}
此外,看起来您不需要以下行:
std::this_thread::sleep_for(std::chrono::毫秒{1000})
简要说明:
async_read操作通过零次或多次调用流的async_read_some函数来实现。调用io_service.run_one()时,您请求只执行一个调用-第一个对异步\u read_some的调用(将跳过其他调用)。这就是为什么您只接收65535个字节,而不调用回调(回调将在最后一次异步读取完成后调用)
io_service.run()和io_service.run_one()在当前线程中运行操作并阻塞线程,直到操作完成,因此不需要调用sleep。 确保io\u服务
(最近称为io\u上下文
)在async\u read
调用后重新启动并运行:
io_service.restart();
io_service.run_one();
确保io\u服务
(最近称为io\u上下文
)在async\u read
调用后重新启动并运行:
io_service.restart();
io_service.run_one();
我通过使用boost::asio::ip::tcp::socket中的成员函数async_read_some解决了这个问题,但我不明白为什么您的建议不适用于我的,我尝试了boost::asio::transfer_justice()、boost::asio::transfer_all()、boost::asio::transfer_至少()。有人能解释这是为什么吗?我做错了什么?实际发送了多少字节?您至少使用了多少字节来传输?如果只发送了一个字节,并且您要求至少接收2个字节,那么您仍然不会看到调用回调(直到连接结束)。如果您需要的逻辑是async\u read\u some
方法,那么使用该方法没有什么错;它应该相当于使用transfer\u至少(1)
。好的,如果服务器发送1字节,我尝试读取2字节