C++中断UDP侦听器.在Xcode中使用oscpack编译

Tom*_*son 5 c++ sockets udp osc

我已成功将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 );
    }
}
Run Code Online (Sandbox Code Playgroud)

尽管编译器建议正确调用所有内容,但我尝试从数据包Listener类调用Break()似乎没有做任何事情:

SocketReceiveMultiplexer s;
s.Break();
Run Code Online (Sandbox Code Playgroud)

我尝试过的另一种方法是根据RunUntilSigInt()函数引发中断标志.在数据包监听器类中:

raise(SIGINT);
Run Code Online (Sandbox Code Playgroud)

但这会终止整个程序,而不是仅仅打破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;
}
Run Code Online (Sandbox Code Playgroud)

我完全坚持这个,任何帮助/建议将不胜感激.

谢谢,汤姆

mat*_*tth 5

我知道这是一个有点老的问题,但是最近我不得不克服这个问题,并且在网上找不到很好的答案。oscpack使用的模型似乎是它们控制无限Run循环,并且您在要从OscPacketListener派生的类中实现要执行的所有操作。如果您不想那样做,则需要Run在单独的线程中运行循环。在oscpack 1.1.0发行版中,似乎不再有内部线程支持。他们在该版本的CHANGES文件中说明,您需要实施自己的线程解决方案。该Run例程SocketReceiveMultiplexer永远不会返回,因此该调用之后的任何代码均无法访问。各种Break例程用于控制程序的执行。Run从另一个线程循环。在下面的示例中,我使用的是c ++ 11,<threads>但是您可以使用选择的任何线程库来完成类似的工作。在我的示例中,您必须

#include <threads>
#include <mutex>
Run Code Online (Sandbox Code Playgroud)

并使用兼容c ++ 11的编译器编译代码。在g ++中,您将需要-std=c++11命令行参数。

如果从SVN中的接收器示例(解析单个消息示例)开始,则可以将main()功能更改为类似

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

在代码中的其他地方打电话

std::thread lt(ListnerThread);
Run Code Online (Sandbox Code Playgroud)

为了启动监听器运行。您必须创建一些在主线程和侦听器线程之间共享信息的方法。一种简单的方法是使用由互斥锁(也是全局变量)包围的全局变量。当然还有其他(更好的?)方法,但这很容易。全局声明它们(按照其示例),而不是在ProcessMessage函数中声明:

std::mutex oscMutex;

bool a1;
osc::int32 a2;
float a3;
const char *a4;
Run Code Online (Sandbox Code Playgroud)

在中ExamplePacketListener,他们在其中设置args流中的变量,然后调用cout您将执行以下操作

oscMutex.lock();
args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
oscMutex.unlock();
Run Code Online (Sandbox Code Playgroud)

只要确保您在代码中的其他位置访问这些变量的方式也lock()unlock()互斥体相同。