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

C++ Interrupting UDP Listener. Compiled using oscpack in Xcode

本文关键字:oscpack 编译 Xcode 中断 UDP 侦听器 C++      更新时间:2023-10-16

我已经成功地将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 );
    }
}

我尝试从packet 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;
}

我完全被这件事困住了,任何帮助/建议都将不胜感激。

谢谢,Tom

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

#include <threads>
#include <mutex>

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

如果您从SVN中的接收方示例(解析单个消息示例)开始,您可以将main()函数更改为类似的函数

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

在代码的其他地方,打一个类似的电话

std::thread lt(ListnerThread);

以便启动侦听器运行。您必须创建一些在主线程和侦听线程之间共享信息的方法。一个简单的方法是使用一个由互斥对象(也称为全局)包围的全局变量。当然还有其他(更好的?)方法,但这很容易。全局声明这些(按照它们的示例),而不是在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()也以相同的方式作为互斥对象,无论您在代码的其他地方访问这些变量。

这是旧的,但这是网络上唯一一个关于这个问题的页面。万一有人需要oit

当我用RunUntilSigInt()函数运行监听器时,使用raise(SIGINT)对我来说很有用。这是一个快速的破解,很难看,但它是这样的:

        if (std::strcmp(m.AddressPattern(), "/test1") == 0) {
            osc::ReceivedMessageArgumentStream args = m.ArgumentStream();
            osc::int32 a1, a2, a3;
            const char *a4;
            args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage;
            raise(SIGINT);
        }

在这种情况下,当我收到一个包时,我会停止侦听器,但您可以根据自己的意愿进行修改。

很抱歉问了一个愚蠢的问题:你试过在中断之前运行侦听器吗?

SocketReceiveMultiplexer s;
s.Run(); // let wire up the things
s.Break();