1

websocketppサーバーをマルチスレッドプロジェクトに統合しようとしています。シングルスレッドアプローチではすべてが正常に機能しますが、バックグラウンドで実行されるendpoint.listen()用に別のboost :: threadを作成するときに問題が発生しました(したがって、メインスレッドの実行が中断されることはありません)。最新のwebsocketppビルドを使用してUbuntu12.0464ビットでBoostv1.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の初心者なので、ここで何か間違ったことをしているのかどうかはわかりません。この問題に取り組むためのより良い(そして実用的な)方法があれば、いくつかの例を見てみたいと思います。私は長い間この問題を理解しようとしてきたので、どんな助けも貴重です。前もって感謝します!

こちらもチェックしてください:gdbstacktracevalgrindの結果

編集: コードサンプルの「while(true)」は、メインスレッドでの処理をシミュレートするためだけにあります。さまざまなタイプのソケット接続、イベント、データ処理、クライアント同期などがバックグラウンドで実行されている大きなプロジェクトにWebSocketサーバーを統合しています。WebSocket接続は、ネイティブクライアントの代わりにWebクライアントを使用してサーバーに接続するためのもう1つの方法を提供します。メインスレッドは必要なものをすべて作成しますが、作成される順序に実際に影響を与えることはできないため、WebSocketサーバーは独自のスレッドで起動する必要があります。

4

2 に答える 2

1

try/catchのスコープ内ですべてのオブジェクトを作成します。このスコープを離れると、これらのオブジェクトは破棄されます。

したがって、オブジェクト定義をtry / catchから移動するか、while(true)ループをその中に移動します。

于 2012-07-16T15:04:31.837 に答える
0

boost::threadスタック上にある可能性があるのに、なぜヒープ上にを作成するのですか?

boost::bindで使用する必要はないのでboost::thread、次のようにする必要があります。

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

はるかに簡単ですよね?

あなたのプログラムの振る舞いについて。ptr->join()そこで呼び出すと、メインスレッドは他のスレッドが終了するのを待ちますが、これは決して起こらないので、もちろんスリープします。参加しないptrecho_endpointhすべてが範囲外になります。次に、他のスレッドは、存在しなくなったオブジェクトを使用しようとします。

@IgorRとして。とは言っwhileても、ループをtry-catchブロック内に配置する必要があります。そうすれば、メインループでの作業は、他のスレッドとそれが使用するオブジェクトがスコープ外になる前に発生する可能性があります。

Boost 1.50以降、boost::threadデストラクタはの動作と一致します。つまり、デストラクタの実行時にスレッドが参加可能かどうかstd::threadを呼び出します。これは、スレッドを参照しているハンドルや他のスタックオブジェクトが存在しなくなっterminate()ても、スレッドが実行を継続するようなエラーを防ぐためです。boost::thread実行を継続したい場合は、明示的に実行する必要があります(ただし、プログラムでは、 andオブジェクトは引き続き存在しなくなり、スレッドは引き続きそれらを使用しようとするdetachため、これは間違っています)。したがって、オブジェクトがスコープ外になる前にあなたはそれかそれのどちらかでなければなりません。echo_endpointhboost::threadjoindetach

于 2012-07-16T15:34:46.630 に答える