C ++ Interrupt UDP listener. Compiled using oscpack in Xcode

I have successfully included the UDPreceive function in my application. HOWEVER! I cannot figure out how to stop the UDP listener from endlessly starting. The OSCPack library has Break () and AsynchronousBreak () functions built into it, but I could not implement them.

in the udpSocket.cpp file in oscpack:

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

My attempt to call Break () from the Listener List class does not work, even though the compiler assumed that everything was being called correctly:

 SocketReceiveMultiplexer s; s.Break(); 

Another method I tried was to raise the interrupt flag according to the RunUntilSigInt () function. Inside the package listener class:

 raise(SIGINT); 

but this terminates the entire program, and not just breaks down from the UDPListener. For reference, here is the RunUntilSigInt () code in udpSocket.cpp:

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

I am completely stuck with this, any help / advice would be greatly appreciated.

Thanks Tom

+5
source share
3 answers

I know this is a somewhat old question, but I had to overcome it recently and did not find a good answer on the Internet. The model used by oscpack seems to be that they drive an infinite Run loop, and you implement everything you want to do inside the class derived from the OscPacketListener. If you do not want to do this, you need to run the Run loop in a separate thread. There seems to be no more internal support for streaming processing in oscpack version 1.1.0. They explain in the CHANGES file for this version that you will need to implement your own streaming solution. The Run procedure in SocketReceiveMultiplexer never returns, so any code after this call is not available. Various Break routines are used to control the execution of a Run loop from another thread. In the example below, I am using C ++ 11 <threads> , but you can use any thread library that you choose to achieve something similar. In my example you need

 #include <threads> #include <mutex> 

and compile your code using the C ++ 11 compiler. In g ++, you will need the command line argument -std=c++11 .

If you start with an example receiver (parsing one example message) in SVN, you can change main() to be something like

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

Somewhere else in your code make a call like

 std::thread lt(ListnerThread); 

to start the listener. You will need to create some ways of exchanging information between your main stream and the listener stream. One simple method is to use a global variable surrounded by a mutex (also global). Of course, there are other (better?) Ways, but it is very easy. Declare them globally (following their example) instead of the ProcessMessage function:

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

Inside ExamplePacketListener , where they set the variables from the args stream and then make a cout call, you do something like

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

Just remember to also lock() and unlock() mutex in the same way, wherever you are in these variables elsewhere in your code.

+4
source

This is old, but it is the only page on the Internet on this issue. If someone needs oit

Using raise(SIGINT) when I start the listener using the RunUntilSigInt() function does the trick for me. This is a quick hack and it is ugly, but it looks like this:

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

In this case, I stop the listener when I receive one packet, but you can change it as you want.

+2
source

Sorry for the stupid question: did you try to start the listener before hacking?

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

Source: https://habr.com/ru/post/1202984/


All Articles