簡體   English   中英

Boost Asio回調不會被調用

[英]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是異步的。 在大多數情況下,客戶端從服務器應用程序接收計算數據,並且必須呈現它們的各種圖形表示。

現在,需要考慮一些關鍵方面:

  1. GUI必須是響應式的,不應該被IO阻止。
  2. 客戶端可以連接/斷開連接。
  3. 流量非常緊張,數據每隔幾秒就會發送/刷新到客戶端,並且必須保持響應(按照第1項)。

根據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_ptrboost::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM