2014-09-19 31 views
5

'da oscpack kullanılarak derlenmiştir Uygulamamda bir UDPreceive işlevini başarıyla dahil ettim. ANCAK! UDP dinleyicisinin sonsuza kadar çalışmasını nasıl durduracağımı anlayamıyorum. OSCPack kitaplığı içinde yerleşik bir Break() ve AsynchronousBreak() vardır, ancak bunları uygulayamadım. oscpack içinde udpSocket.cpp dosyasında C++ UDP Dinleyicisi'ni Durdurma. Xcode

:

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

her şey doğru şekilde çağrıldığını ileri süren derleyici rağmen bir şey yapmak görünmüyor paket Dinleyici sınıfından Sonu'nu() çağırmak için My girişimi :

SocketReceiveMultiplexer s; 
s.Break(); 

denedim diğer bir yöntem RunUntilSigInt() işlevi ile uygun olarak, bir kesme bayrağının oldu.

raise(SIGINT); 

ama bu yerine sadece UDPListener kopuş daha bütün program sona erer: paket dinleyici sınıfı içinde.

Ben tamamen bu sefer mahsur kaldım
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; 
} 

, herhangi bir yardım/tavsiye büyük takdir edilecektir: Referans olarak aşağıda udpSocket.cpp içinde RunUntilSigInt() kodudur.

sayesinde aptal soru için üzgünüm Tom

+0

Yerel olarak 'stop' datagramı gönderilsin mi? –

+0

@MartinJames, bunun için teşekkürler, böyle bir şey? http://stackoverflow.com/questions/4670664/interrupt-a-thread-in-datagramsocket-receive –

cevap

4

Bunun biraz eski bir soru olduğunu biliyorum, ancak bu sonun üstesinden gelmek zorunda kaldım ve çevrimiçi olarak iyi bir yanıt bulamadım. Oscpack tarafından kullanılan model, sonsuz Run döngüsünü kontrol ettikleri ve OscPacketListener'den türetilen bir sınıf içinde yapmak istediğiniz her şeyi uyguladıkları gibi görünüyor. Bu şekilde şeyler yapmak istemiyorsanız, Run döngüsünü ayrı bir iş parçacığında çalıştırmanız gerekir. Oscpack 1.1.0 sürümünde görünüyor, artık iş parçacığı için dahili destek yok. Bu sürümde kendi iş parçacığı çözümünüzü uygulamanız gerekeceği için CHANGES dosyasında açıklarlar. SocketReceiveMultiplexer numaralı telefondan Run rutini asla geri dönmez, bu nedenle bu aramadan sonra herhangi bir kod ulaşılamaz. Çeşitli Break rutinleri, farklı bir iş parçacığından Run döngüsünün yürütülmesini denetlemek içindir. Aşağıdaki örnekte C++ 11 <threads> kullanıyorum ancak benzer bir şeyi başarmak için seçtiğiniz herhangi bir iş parçacığı kütüphanesini kullanabilirsiniz. Benim örnekte,

#include <threads> 
#include <mutex> 

gerekecek ve bir C++ 11 uyumlu derleyici ile kodunuzu derlemek. G ++ 'da -std=c++11 komut satırı argümanına ihtiyacınız olacaktır.

Eğer SVN'de receiver example (ayrıştırma tek iletilerin örnek) ile başlarsanız, bir şey kodunuzda başka

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

Somewhere gibi

gibi bir çağrı yapmak olmaya main() işlevini değiştirebilir Dinleyiciyi çalıştırmak için
std::thread lt(ListnerThread); 

. Ana iş parçacığınız ve dinleyici iş parçacığı arasında bilgi paylaşımı için bazı araçlar oluşturmanız gerekir.Basit bir yöntem, bir mutex (global) ile çevrelenmiş global bir değişken kullanmaktır. Kesinlikle başka (daha iyi?) Yollar vardır ama bu çok kolaydır. ExamplePacketListener İçinde

std::mutex oscMutex; 

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

, onlar

böyle bir şey yapsın cout için bir çağrı yapmak sonra args akışından değişkenleri ayarlamak ve: (kendi Örneğin aşağıdaki) yerine ProcessMessage işlev içinde global olarak bu beyan
oscMutex.lock(); 
args >> a1 >> a2 >> a3 >> a4 >> osc::EndMessage; 
oscMutex.unlock(); 

Ayrıca, kodunuzdaki başka herhangi bir yere erişebildiğiniz her yerde, aynı şekildeve unlock() muteksini de kullandığınızdan emin olun.

+0

Matth, işaretçiler için teşekkürler! Farklı bir iş parçasında çalıştırılmasının gerekli olduğunu düşündüm, ancak bunu iOS'ta uygulayamadı. 2015'te tekrar bu projede çalışacağım, bu yüzden yönteminizi denemek için zamanım olacak. Şerefe, Tom. –

+0

Merhabalar. Kendi ana döngümüm olduğu için, ana döngümde osc :: UdpSocket :: ReceiveFrom() yöntemini dahil etmenin başka bir yolu var mı? – nass

0

: Eğer kırılma önce dinleyici çalıştırmak çalıştı?

+0

Merhaba Yuri, Evet, dinleyici ana programımdan Run(). Yukarıda bahsettiğim gibi, kod mükemmel çalışıyor ... dinleyiciden koparamam ve diğer görevlerle devam edemem! Sağol Tom. –

2

Bu eskidir, ancak web üzerinde bu sorunla ilgili tek sayfa budur.

raise(SIGINT)'un RunUntilSigInt() işlevini kullanarak dinleyiciyi çalıştırdığımda işlev benim için hile yapar. Bu hızlı kesmek ve o çirkin ama böyle gider i bir paketi aldığınızda

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

Bu durumda, ben dinleyici durdurmak, ancak istediğiniz gibi değişiklik yapabilirsiniz.