[英]Boost Asio callback doesn't get called
我正在使用Boost.Asio进行网络操作,他们必须(实际上,可以,没有复杂的数据结构或任何东西)保持相当低的水平,因为我无法负担序列化开销的奢侈(和我发现的libs提供足够好的表现似乎非常适合我的情况)。
问题在于我正在从客户端进行异步写入(在QT中,但这应该与此无关)。 async_write
中指定的回调不会被调用,而且我完全不知道为什么。 代码是:
void SpikingMatrixClient::addMatrix() {
std::cout << "entered add matrix" << std::endl;
int action = protocol::Actions::AddMatrix;
int matrixSize = this->ui->editNetworkSize->text().toInt();
std::ostream out(&buf);
out.write(reinterpret_cast<const char*>(&action), sizeof(action));
out.write(reinterpret_cast<const char*>(&matrixSize), sizeof(matrixSize));
boost::asio::async_write(*connection.socket(), buf.data(),
boost::bind(&SpikingMatrixClient::onAddMatrix, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}
它调用第一次写入。 回调是
void SpikingMatrixClient::onAddMatrix(const boost::system::error_code& error, size_t bytes_transferred) {
std::cout << "entered onAddMatrix" << std::endl;
if (!error) {
buf.consume(bytes_transferred);
requestMatrixList();
} else {
QString message = QString::fromStdString(error.message());
this->ui->statusBar->showMessage(message, 15000);
}
}
即使服务器接收到所有数据,也不会调用回调。 任何人都可以想到它可能会这样做的任何原因吗?
PS这个连接有一个包装器,是的,可能会有一个连接器。 一两天前放弃它,因为我找不到这个回调的问题。
正如所建议的那样,发布一个我认为最合适的解决方案(至少目前为止)。
客户端应用程序是用QT编写的,我需要IO是异步的。 在大多数情况下,客户端从服务器应用程序接收计算数据,并且必须呈现它们的各种图形表示。
现在,需要考虑一些关键方面:
根据Boost.Asio文档,
多个线程可以调用io_service :: run()来设置一个线程池,从中可以调用完成处理程序。 请注意,已加入io_service池的所有线程都被视为等效,并且io_service可以以任意方式在它们之间分配工作。
请注意, io_service.run()
阻塞,直到io_service用完为止。
考虑到这一点,明确的解决方案是从另一个线程运行io_service.run()
。 相关的代码片段是
void SpikingMatrixClient::connect() {
Ui::ConnectDialog ui;
QDialog *dialog = new QDialog;
ui.setupUi(dialog);
if (dialog->exec()) {
QString host = ui.lineEditHost->text();
QString port = ui.lineEditPort->text();
connection = TcpConnection::create(io);
boost::system::error_code error = connection->connect(host, port);
if (!error) {
io = boost::shared_ptr<boost::asio::io_service>(new boost::asio::io_service);
work = boost::shared_ptr<boost::asio::io_service::work>(new boost::asio::io_service::work(*io));
io_threads.create_thread(boost::bind(&SpikingMatrixClient::runIo, this, io));
}
QString message = QString::fromStdString(error.message());
this->ui->statusBar->showMessage(message, 15000);
}
}
用于连接和启动IO,其中:
work
是一个私有的boost::shared_ptr
,它传递给boost::asio::io_service::work
对象, io
是一个私有的boost::shared_ptr
到boost::asio::io_service
, connection
是一个boost::shared_ptr
连接到我的连接包装器类,而connect()
调用使用一个解析器等来连接套接字,那里有很多例子。 io_threads
是一个私有的boost::thread_group
。 当然,如果需要,可以使用某些typedef缩短它。
TcpConnection
是我自己的连接包装器实现,它现在缺乏功能,我想我可以在恢复时将整个线程移动到它中。 无论如何,这个片段应该足以让这个想法得到......
断开连接部分如下:
void SpikingMatrixClient::disconnect() {
work.reset();
io_threads.join_all();
boost::system::error_code error = connection->disconnect();
if (!error) {
connection.reset();
}
QString message = QString::fromStdString(error.message());
this->ui->statusBar->showMessage(message, 15000);
}
io_service
最终可能会耗尽工作, disconnect()
在后台调用socket上的shutdown()
和close()
,如果没有错误,则破坏连接指针。 请注意,在此片段中断开连接时出现错误时没有错误处理,但是通过检查错误代码(看起来更像C)或者从disconnect()
抛出,可以很好地完成错误处理。其中的错误代码表示尝试断开连接后出错。
我遇到了类似的问题(回调未被触发)但情况与此问题不同( io_service
有工作但仍然不会触发处理程序)。 无论如何我会发布这个,也许它会帮助别人。
在我的程序中,我设置了一个async_connect()
然后是io_service.run()
,它按预期阻塞。
async_connect()
按预期进入on_connect_handler()
,然后触发async_write()
。
即使连接的另一端已收到所有数据并且甚至已发回响应, on_write_complete_handler()
也不会触发。
我发现它是由我在on_connect_handler()
放置程序逻辑引起的。 具体来说,在建立连接之后和我调用async_write()
,我进入了一个无限循环来执行任意逻辑,不允许on_connect_handler()
退出。 我认为这导致io_service
无法执行其他处理程序,即使它们的条件得到满足,因为它被卡在这里。 (我有很多误解,并认为io_service
会为每个async_x()
调用自动生成线程)
希望有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.