簡體   English   中英

使用websocketpp庫在多線程程序中為endpoint.listen()創建單獨的增強線程

[英]Creating a separate boost thread for endpoint.listen() in a multithreaded program using websocketpp library

我正在嘗試將websocketpp服務器集成到多線程項目中。 一切都在單線程方法中運行良好,但是在為Endpoint.listen()創建單獨的boost :: thread時會在后台運行時遇到問題(因此不會中斷主線程的執行)。 我已經在帶有最新版本的websocketpp的Ubuntu 12.04 64位上使用Boost v1.46.1和v1.50.0嘗試了該代碼。 下面是一個代碼示例和我的方法的說明。

#include <websocketpp/websocketpp.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <exception>

using websocketpp::server;

class echo_server_handler : public server::handler {
public:
    void on_message(connection_ptr con, message_ptr msg) {
        con->send(msg->get_payload(),msg->get_opcode());
    std::cout << "Got message: " << msg->get_payload() << std::endl;
    }
};


int main(int argc, char* argv[]) {

    unsigned short port = 9002;

    try {       
        server::handler::ptr h(new echo_server_handler());
        server echo_endpoint(h);

        echo_endpoint.alog().unset_level(websocketpp::log::alevel::ALL);
        echo_endpoint.elog().unset_level(websocketpp::log::elevel::ALL);

        echo_endpoint.alog().set_level(websocketpp::log::alevel::CONNECT);
        echo_endpoint.alog().set_level(websocketpp::log::alevel::DISCONNECT);

        echo_endpoint.elog().set_level(websocketpp::log::elevel::RERROR);
        echo_endpoint.elog().set_level(websocketpp::log::elevel::FATAL);

        std::cout << "Starting WebSocket echo server on port " << port << std::endl;

        //Getting pointer to the right function
         void(websocketpp::role::server<websocketpp::server>::*f)(uint16_t,size_t) =
                &websocketpp::role::server<websocketpp::server>::listen;

        std::cout << "Starting WSServer thread... \n" << std:endl;
        boost::shared_ptr<boost::thread> ptr(new boost::thread(boost::bind(f, &echo_endpoint, port, 1)));
    //ptr->join();

    } catch (std::exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
    }

    //Simulating processing in the main thread
    while(true) {std::cout << "Main thread processing..."<<std::endl; sleep(5);}


    return 0;

}

如果我用ptr-> join()編譯代碼 偵聽線程工作正常,但使主線程進入睡眠狀態。 如果我省略ptr-> join()並讓偵聽線程在后台運行,則在創建線程后會遇到錯誤:

/usr/local/boost_1_50_0/libbin/include/boost/thread/pthread/recursive_mutex.hpp:105:void boost :: recursive_mutex :: lock():斷言`!pthread_mutex_lock(&m)'失敗。

我對線程或增強線程的經驗不是很豐富,對於websocketpp來說還不是很新,所以我不確定在這里是否做錯了什么。 如果有解決此問題的更好(可行)方法,我希望看到一些示例。 我已經很長時間試圖解決這個問題了,所以任何幫助都是無價的。 提前致謝!

另請檢出: gdb stacktracevalgrind結果

編輯:代碼示例中的“ while(true)”僅用於模擬主線程中的處理。 我正在將Websocket服務器集成到一個大型項目中,該項目在后台運行不同類型的套接字連接,事件,數據處理,客戶端同步等。 Websocket連接提供了另一種使用Web客戶端而不是本機客戶端連接到服務器的方法。 主線程會創建所有必要的內容,但是我不能真正影響它們的創建順序,因此websocket服務器必須在其自己的線程中啟動。

您在try / catch范圍內創建所有對象。 當您離開此范圍時,這些對象將被銷毀。

因此,可以將對象定義移出try / catch,或將while(true)循環移入其中。

為什么要在堆上創建boost::thread時將其放在堆棧上?

您不需要將boost::bindboost::thread boost::bind使用,因此它應該很簡單:

    boost::thread t(f, &echo_endpoint, port, 1);

簡單得多,不是嗎?

至於您程序的行為。 如果您在其中調用ptr->join() ,那么主線程將等待另一個線程完成,這永遠不會發生,因此它會休眠。 如果不加入,則ptrecho_endpoint以及h都超出范圍。 然后另一個線程將嘗試使用不再存在的對象。

作為@IgorR。 ,您應該將while循環放在try-catch塊內,這樣主循環中的工作可以其他線程及其使用的對象超出范圍之前進行。

從Boost 1.50開始, boost::thread析構函數與std::thread的行為匹配,即,如果線程在其析構函數運行時是可連接的,它將調用terminate() 這是為了防止出現這種錯誤,即使引用該線程的boost::thread句柄和其他堆棧對象不再存在,該線程也繼續運行。 如果希望它繼續運行,則必須顯式detach它(但是在您的程序中這仍然是錯誤的,因為echo_endpointh對象將仍然不存在,並且線程仍將嘗試使用它們。)因此,在進行boost::thread之前boost::thread對象超出范圍,您應該joindetach它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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