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 );
    }
}

我尝试从数据包侦听器类调用 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 兼容的编译器编译您的代码。在 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()

于 2014-12-05T10:12:17.500 回答
2

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

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

        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);
        }

在这种情况下,我会在收到一包时停止监听器,但您可以根据需要对其进行修改。

于 2015-12-19T21:17:42.513 回答
0

抱歉,愚蠢的问题:您是否尝试在中断之前运行侦听器?

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