gpt4 book ai didi

c++ - boost asio udp 套接字 async_receive_from 不调用处理程序

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:19:26 26 4
gpt4 key购买 nike

我想创建一个自治线程,专门用于使用 boost 库 (asio) 从 UDP 套接字接收数据。这个线程应该是一个无限循环,由从 UDP 套接字接收到的一些数据触发。在我的应用程序中,我需要使用异步接收操作。

如果我使用同步函数 receive_from,一切都会按预期工作。

但是,如果我使用 async_receive_from,则永远不会调用处理程序。由于我使用信号量来检测是否已接收到某些数据,因此程序锁定并且永远不会触发循环。

我已经(使用网络分析器)验证发送方设备在 UDP 套接字上正确发送数据。

我已在以下代码中找出问题。

#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 是首选,但出于调试目的,我在上面的代码中使用了阻塞等待。

我错过了什么吗?我的错误在哪里?

最佳答案

您对 io_service.run() 的调用正在退出,因为 io_service 没有工作要做。然后代码进入 while 循环并调用 m_socket.async_receive_from。此时 io_service 没有运行,因此它永远不会读取数据并调用您的处理程序。

您需要在调用 io_service run 之前安排要执行的工作:

即:

// Configure io service
ReceiveUDP receiver;

m_socket.open(udp::v4());
m_socket.bind(m_local_endpoint);
m_socket.async_receive_from(
boost::asio::buffer(recv_buf),
m_sender_endpoint,
boost::bind(&ReceiveUDP::_HandleReceiveFrom, receiver,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

处理函数将执行以下操作:

// start the io service
void HandleReceiveFrom(
const boost::system::error_code& error,
size_t received_bytes)
{
m_receive_semaphore.post();

// schedule the next asynchronous read
m_socket.async_receive_from(
boost::asio::buffer(recv_buf),
m_sender_endpoint,
boost::bind(&ReceiveUDP::_HandleReceiveFrom, receiver,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));

m_read_bytes = received_bytes;
}

然后您的线程只需等待信号量:

while (1)
{
m_receive_semaphore.wait();
std::cout.write(recv_buf.data(), m_read_bytes);
}

注意事项:

  1. 你真的需要这个额外的线程吗?处理程序是完全异步的,boost::asio 可用于管理线程池(参见:think-async)
  2. 请不要在变量/函数名称中使用下划线后跟大写字母。它们是保留的。

关于c++ - boost asio udp 套接字 async_receive_from 不调用处理程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13579879/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com