[英]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.