5

UDPreceive 関数をアプリケーションに組み込むことに成功しました。でも!UDPリスナーが無限に実行されるのを止める方法がわかりません。OSCPack ライブラリには Break() と AsynchronousBreak() が組み込まれていますが、これらを実装できませんでした。

oscpack 内の udpSocket.cpp ファイル:

void Run() //the listener function (WORKING!)
{
    break_ = false; 
    //UDP Listener Code

    void Break()
    {
        break_ = true;
    }
    void AsynchronousBreak()
    {
        break_ = true;
        // Send a termination message to the asynchronous break pipe, so select() will return
        write( breakPipe_[1], "!", 1 );
    }
}

コンパイラがすべてが正しく呼び出されていることを示唆しているにもかかわらず、パケット Listener クラスから Break() を呼び出そうとしても、何もしないようです。

SocketReceiveMultiplexer s;
s.Break();

私が試した別の方法は、RunUntilSigInt() 関数に従って割り込みフラグを立てることでした。パケット リスナー クラス内:

raise(SIGINT);

ただし、これは UDPListener から単に中断するのではなく、プログラム全体を終了させます。参考までに、udpSocket.cpp 内の RunUntilSigInt() コードを次に示します。

void SocketReceiveMultiplexer::RunUntilSigInt()
{
    assert( multiplexerInstanceToAbortWithSigInt_ == 0 ); /* at present we support only one multiplexer instance running until sig int */
    multiplexerInstanceToAbortWithSigInt_ = this;
    signal( SIGINT, InterruptSignalHandler );
    impl_->Run();
    signal( SIGINT, SIG_DFL );
    multiplexerInstanceToAbortWithSigInt_ = 0;
}

私はこれに完全に行き詰まっています。どんな助けやアドバイスも大歓迎です。

ありがとう、トム

4

3 に答える 3

5

これはやや古い質問であることは知っていますが、最近これを克服する必要があり、オンラインで適切な回答が見つかりませんでした. oscpack が使用するモデルは、無限Runループを制御するようで、OscPacketListener から派生したクラス内でやりたいことすべてを実装します。そのようにしたくない場合はRun、別のスレッドでループを実行する必要があります。oscpack 1.1.0 リリースでは、スレッドの内部サポートがなくなったようです。彼らは、そのリリースのCHANGESファイルで、独自のスレッド ソリューションを実装する必要があると説明しています。のRunルーチンSocketReceiveMultiplexerは返されないため、その呼び出しの後のコードには到達できません。さまざまなBreakルーチンは、Run別のスレッドからループします。以下の例では c++11 を使用し<threads>ていますが、任意のスレッド ライブラリを使用して同様のことを実現できます。私の例では、あなたはする必要があります

#include <threads>
#include <mutex>

c++11 互換コンパイラでコードをコンパイルします。-std=c++11g++ では、コマンド ライン引数が必要です。

SVNのレシーバーの例(単一メッセージの解析の例)から始める場合、main()関数を次のように変更できます。

void ListnerThread()
{
    PacketListener listener;
    UdpListeningReceiveSocket s(
            IpEndpointName( IpEndpointName::ANY_ADDRESS, PORT ),
            &listener );
    s.Run();
}

コードのどこかで、次のように呼び出します

std::thread lt(ListnerThread);

リスナーの実行を開始するため。メイン スレッドとリスナー スレッドの間で情報を共有する手段を作成する必要があります。簡単な方法の 1 つは、ミューテックス (これもグローバル) で囲まれたグローバル変数を使用することです。確かに他の (より良い?) 方法がありますが、これは非常に簡単です。ProcessMessage関数内ではなく、これらをグローバルに (例に従って) 宣言します。

std::mutex oscMutex;

bool a1;
osc::int32 a2;
float a3;
const char *a4;

内部ではExamplePacketListener、ストリームから変数を設定し、args次のように呼び出しcoutます。

oscMutex.lock();
args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
oscMutex.unlock();

コード内の他の場所でこれらの変数にアクセスする場合は、必ず同じ方法lock()でミューテックスも実行してください。unlock()

于 2014-12-05T10:12:17.500 に答える
0

ばかげた質問で申し訳ありません: 壊れる前にリスナーを実行しようとしましたか?

SocketReceiveMultiplexer s;
s.Run(); // let wire up the things
s.Break();
于 2014-09-19T16:01:30.513 に答える