我正在使用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));
}
Run Code Online (Sandbox Code Playgroud)
它调用第一次写入.回调是
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);
}
}
Run Code Online (Sandbox Code Playgroud)
即使服务器接收到所有数据,也不会调用回调.任何人都可以想到它可能会这样做的任何原因吗?
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);
}
}
Run Code Online (Sandbox Code Playgroud)
用于连接和启动 IO,其中:
work是它所传递的对象boost::shared_ptr的私有对象,boost::asio::io_service::workioboost::shared_ptr是a 的私有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);
}
Run Code Online (Sandbox Code Playgroud)
io_service最终可能会耗尽工作,disconnect()在幕后的套接字上,如果没有错误,则销毁连接指针。shutdown()close()请注意,在这段代码中断开连接时发生错误时没有错误处理,但它可以很好地完成,可以通过检查错误代码(看起来更像 C),或者从 if 中抛出错误disconnect()代码它表示尝试断开连接后出现错误。
| 归档时间: |
|
| 查看次数: |
2802 次 |
| 最近记录: |