Я успешно включил функцию UDPreceive в свое приложение. ТЕМ НЕ МЕНИЕ! Я не могу понять, как остановить бесконечный запуск прослушивателя UDP. Библиотека OSCPack имеет встроенные функции Break () и AsynchronousBreak (), но я не смог реализовать их.
в файле udpSocket.cpp в рамках пакета 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 );
}
}
Моя попытка вызвать Break () из класса Listener пакета, похоже, ничего не делает, несмотря на то, что компилятор предположил, что все вызывается правильно:
SocketReceiveMultiplexer s;
s.Break();
Другой метод, который я попробовал, состоял в том, чтобы поднять флаг прерывания в соответствии с функцией RunUntilSigInt (). Внутри класса прослушивателя пакетов:
raise(SIGINT);
но это завершает всю программу, а не просто отрывается от UDPListener. Для справки, вот код RunUntilSigInt () в 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;
}
Я полностью застрял на этом, любая помощь / совет будет принята с благодарностью.
Спасибо,
Том
Я знаю, что это довольно старый вопрос, но недавно мне пришлось его преодолеть, и я не нашел хорошего ответа в Интернете. Модель, используемая oscpack, похоже, что они контролируют бесконечность Run
цикл, и вы реализуете все, что вы хотите сделать внутри класса, производного от OscPacketListener. Если вы не хотите делать что-то таким образом, вам нужно запустить Run
цикл в отдельном потоке. Кажется, в выпуске oscpack 1.1.0 больше нет внутренней поддержки многопоточности. Они объясняют в ИЗМЕНЕНИЯ файл для этого выпуска, который вам понадобится для реализации собственного решения для потоков. 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()
мьютекс таким же образом, где бы вы ни обращались к этим переменным в другом месте вашего кода.
Это старая версия, но это единственная страница в Интернете об этой проблеме. На случай, если кому-то понадобится 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);
}
В этом случае я останавливаю слушателя, когда получаю один пакет, но вы можете изменить его по своему желанию.
Извините за глупый вопрос: вы пытались запустить слушателя до взлома?
SocketReceiveMultiplexer s;
s.Run(); // let wire up the things
s.Break();