2014-09-19 12 views
5

Tôi đã kết hợp thành công hàm UDPreceive vào ứng dụng của mình. TUY NHIÊN! Tôi không thể tìm ra cách để ngăn chặn người nghe UDP chạy vô hạn. Thư viện OSCPack có một Break() và AsynchronousBreak() được tích hợp vào nó, nhưng tôi đã không thể thực hiện chúng.C++ Làm gián đoạn Trình nghe UDP. Biên dịch bằng oscpack trong Xcode

trong file udpSocket.cpp trong 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); 
    } 
} 

nỗ lực của tôi để gọi Break() từ lớp Listener gói không xuất hiện để làm gì cả, mặc dù trình biên dịch cho thấy rằng tất cả mọi thứ được gọi chính xác :

SocketReceiveMultiplexer s; 
s.Break(); 

Một phương pháp khác mà tôi đã thử là tăng cờ ngắt theo hàm RunUntilSigInt(). Trong lớp người nghe gói:

raise(SIGINT); 

nhưng điều này chấm dứt toàn bộ chương trình, thay vì chỉ phá vỡ từ UDPListener. Để tham khảo, đây là RunUntilSigInt() mã trong 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; 
} 

Tôi hoàn toàn bị mắc kẹt trên một này, bất kỳ sự giúp đỡ/lời khuyên sẽ được đánh giá rất nhiều.

Cảm ơn, Tom

+0

Gửi datagram 'dừng' cục bộ? –

+0

@MartinJames, cảm ơn vì điều đó, một cái gì đó như thế này? http://stackoverflow.com/questions/4670664/interrupt-a-thread-in-datagramsocket-receive –

Trả lời

4

Tôi biết đây là câu hỏi hơi cũ, nhưng tôi phải khắc phục vấn đề này gần đây và không tìm thấy câu trả lời hay trên mạng. Mô hình được sử dụng bởi oscpack dường như là chúng kiểm soát vòng lặp vô hạn Run và bạn thực hiện mọi thứ bạn muốn làm bên trong một lớp có nguồn gốc từ OscPacketListener. Nếu bạn không muốn làm những việc theo cách đó, bạn cần chạy vòng Run trong một chuỗi riêng biệt. Có vẻ như trong bản phát hành oscpack 1.1.0, không có hỗ trợ nội bộ cho luồng nữa. Chúng giải thích trong tệp CHANGES cho bản phát hành đó mà bạn sẽ cần phải triển khai giải pháp luồng của riêng mình. Các thói quen Run trong SocketReceiveMultiplexer không bao giờ trở lại, vì vậy bất kỳ mã sau cuộc gọi đó là không thể truy cập. Các thói quen khác nhau của Break là để kiểm soát việc thực hiện vòng lặp Run từ một luồng khác. Trong ví dụ dưới đây tôi đang sử dụng C++ 11 <threads> nhưng bạn có thể sử dụng bất kỳ thư viện luồng nào mà bạn chọn để thực hiện điều gì đó tương tự. Trong ví dụ của tôi, bạn sẽ phải

#include <threads> 
#include <mutex> 

và biên dịch mã của bạn bằng trình biên dịch tương thích C++ 11. Trong g ++, bạn sẽ cần đối số dòng lệnh -std=c++11.

Nếu bạn bắt đầu với (tin nhắn phân tích cú pháp đơn chẳng hạn) receiver example trong SVN, bạn có thể thay đổi main() chức năng để có một cái gì đó giống như

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

Một nơi nào đó khác trong mã của bạn, thực hiện cuộc gọi như

std::thread lt(ListnerThread); 

để bắt đầu trình nghe đang chạy. Bạn sẽ phải tạo một số phương tiện chia sẻ thông tin giữa chủ đề chính của bạn và chuỗi trình nghe.Một phương pháp đơn giản là sử dụng một biến toàn cầu được bao quanh bởi một mutex (cũng toàn cầu). Có những cách khác (tốt hơn?) Nhưng điều này rất dễ dàng. Khai báo các trên toàn cầu (theo gương của họ) thay vì trong ProcessMessage chức năng:

std::mutex oscMutex; 

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

Bên trong ExamplePacketListener, nơi họ thiết lập các biến từ dòng args và sau đó thực hiện cuộc gọi đến cout bạn sẽ làm điều gì đó như

Chỉ cần chắc chắn cũng lock()unlock() mutex theo cùng một cách bất cứ nơi nào bạn truy cập các biến đó ở nơi khác trong mã của bạn.

+0

Matth, cảm ơn các con trỏ! Tôi thấy nó cần phải được chạy trong một chủ đề khác nhau, nhưng không thể quản lý để thực hiện điều này trong iOS. Tôi sẽ làm việc trên dự án này một lần nữa vào năm 2015, vì vậy tôi sẽ có thời gian để thử phương pháp của bạn. Chúc mừng, Tom. –

+0

Xin chào! Vì tôi có vòng lặp chính của riêng tôi, có cách nào khác để kết hợp các osc :: UdpSocket :: ReceiveFrom() trong vòng lặp chính của tôi? – nass

0

Xin lỗi vì câu hỏi ngu ngốc: bạn đã cố gắng chạy người nghe trước khi phá vỡ?

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

Hi Yuri, Vâng, người nghe là Run() từ chương trình chính của tôi. Như tôi đã đề cập ở trên, mã đang chạy hoàn hảo ... ngoài thực tế tôi không thể thoát khỏi người nghe và tiếp tục với các nhiệm vụ khác !!! Cảm ơn, Tom. –

2

Đây là phiên bản cũ nhưng đây là trang duy nhất trên web về sự cố này. Trong trường hợp ai đó cần oit

Sử dụng raise(SIGINT) khi tôi chạy trình nghe với chức năng RunUntilSigInt() sẽ thực hiện thủ thuật cho tôi. Đó là một cách nhanh chóng hack và nó là xấu xí nhưng nó đi như thế này:

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

Trong trường hợp này, tôi dừng lại lắng nghe khi tôi nhận được một gói, nhưng bạn có thể sửa đổi nó như bạn muốn.

Các vấn đề liên quan