Chcę utworzyć autonomiczny wątek poświęcony wyłącznie na odbieranie danych z gniazda UDP za pomocą bibliotek boost (asio). Ten wątek powinien być nieskończoną pętlą uruchamianą przez niektóre dane odebrane z gniazda UDP. W mojej aplikacji potrzebuję użyć asynchronicznej operacji odbierania.doładowanie asio udp socket async_receive_from nie wywołuje programu obsługi
Jeśli korzystam z funkcji synchronicznej receive_from, wszystko działa zgodnie z oczekiwaniami.
Jednak jeśli używam async_receive_from handler nigdy nie jest wywoływana. Ponieważ używam semafora do wykrycia, że niektóre dane zostały odebrane, program blokuje się i pętla nigdy nie jest wyzwalana.
Sprawdziłem (za pomocą analizatora sieci), czy urządzenie wysyłające prawidłowo wysyła dane do gniazda UDP.
Wyizolowałem problem w poniższym kodzie.
#include <boost\array.hpp>
#include <boost\asio.hpp>
#include <boost\thread.hpp>
#include <boost\interprocess\sync\interprocess_semaphore.hpp>
#include <iostream>
typedef boost::interprocess::interprocess_semaphore Semaphore;
using namespace boost::asio::ip;
class ReceiveUDP
{
public:
boost::thread* m_pThread;
boost::asio::io_service m_io_service;
udp::endpoint m_local_endpoint;
udp::endpoint m_sender_endpoint;
udp::socket m_socket;
size_t m_read_bytes;
Semaphore m_receive_semaphore;
ReceiveUDP() :
m_socket(m_io_service),
m_local_endpoint(boost::asio::ip::address::from_string("192.168.0.254"), 11),
m_sender_endpoint(boost::asio::ip::address::from_string("192.168.0.11"), 5550),
m_receive_semaphore(0)
{
Start();
}
void Start()
{
m_pThread = new boost::thread(&ReceiveUDP::_ThreadFunction, this);
}
void _HandleReceiveFrom(
const boost::system::error_code& error,
size_t received_bytes)
{
m_receive_semaphore.post();
m_read_bytes = received_bytes;
}
void _ThreadFunction()
{
try
{
boost::array<char, 100> recv_buf;
m_socket.open(udp::v4());
m_socket.bind(m_local_endpoint);
m_io_service.run();
while (1)
{
#if 1 // THIS WORKS
m_read_bytes = m_socket.receive_from(
boost::asio::buffer(recv_buf), m_sender_endpoint);
#else // THIS DOESN'T WORK
m_socket.async_receive_from(
boost::asio::buffer(recv_buf),
m_sender_endpoint,
boost::bind(&ReceiveUDP::_HandleReceiveFrom, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
/* The program locks on this wait since _HandleReceiveFrom
is never called. */
m_receive_semaphore.wait();
#endif
std::cout.write(recv_buf.data(), m_read_bytes);
}
m_socket.close();
}
catch (std::exception& e)
{
std::cerr << e.what() << std::endl;
}
}
};
void main()
{
ReceiveUDP receive_thread;
receive_thread.m_pThread->join();
}
timed_wait na semafora ma być jednak korzystne dla celów debugowania użyłem czekać blokowania jak w powyższym kodzie.
Czy coś mi umknęło? Gdzie jest mój błąd?
Dziękuję bardzo! Zmodyfikowałem kod zgodnie z Twoimi sugestiami i wszystko działa dobrze. Skonfigurowałem usługę We/Wy przed utworzeniem wątku. Wezwanie do io_service.run() jest tylko po utworzeniu wątku: \t void start() { \t \t \t m_socket.open (udp :: v4()); \t \t m_socket.bind (m_local_endpoint); \t \t StartRead(); \t \t m_pThread = new boost :: thread (& ReceiveUDP :: _ ThreadFunction, this); \t \t m_io_service.run(); \t} Where StartRead() to połączenie z async_receive_from. Jeszcze raz dziękuję. – arms
Dzięki za to, zwariowałem. – Alex