сокеты — C ++ Прерывающий UDP Listener. Скомпилировано с помощью oscpack в Xcode

Я успешно включил функцию 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;
}

Я полностью застрял на этом, любая помощь / совет будет принята с благодарностью.

Спасибо,
Том

5

Решение

Я знаю, что это довольно старый вопрос, но недавно мне пришлось его преодолеть, и я не нашел хорошего ответа в Интернете. Модель, используемая 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() мьютекс таким же образом, где бы вы ни обращались к этим переменным в другом месте вашего кода.

4

Другие решения

Это старая версия, но это единственная страница в Интернете об этой проблеме. На случай, если кому-то понадобится 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);
}

В этом случае я останавливаю слушателя, когда получаю один пакет, но вы можете изменить его по своему желанию.

2

Извините за глупый вопрос: вы пытались запустить слушателя до взлома?

SocketReceiveMultiplexer s;
s.Run(); // let wire up the things
s.Break();
0
По вопросам рекламы [email protected]