我正在尝试使用Boost asio编写一个小型UDP代理。在其中,我需要读取一个套接字,如果该套接字接收到数据报,则应在特定时间后触发回调,转发数据报。它还应该立即准备好接收新的数据报。
我的问题是,当我的代码不在类中时,它可以工作,但一旦我尝试将其创建为类,代码就会停止工作。我很确定我错过了一些关键的东西,因为我对异步增强非常陌生。
工作的代码看起来是这样的,我得到了计时器按预期命中的输出。
#include <iostream>
#include <boost/asio.hpp>
void receive(udp::socket &socket, io_context &ioContext) {
udp::endpoint receive_endpoint;
std::array<char, 8192> buf;
socket.async_receive_from(buffer(buf, buf.size()), receive_endpoint,
[&](const boost::system::error_code& error, std::size_t bytesReceived) {
if (!error && bytesReceived > 0) {
std::cout << "Got a package" << std::endl;
boost::asio::steady_timer timer = boost::asio::steady_timer(ioContext, boost::asio::chrono::milliseconds(100));
timer.async_wait([&](const boost::system::error_code& ec) {
std::cout << "Timer hit" << std::endl;
});
receive(socket, ioContext);
} else {
std::cout << "Error receiving data from client" << std::endl;
}
});
}
int main() {
boost::asio::io_context ioContext;
udp::socket socket(ioContext);
socket.open(udp::v4());
udp::endpoint localEndpoint(ip::address::from_string("127.0.0.1"), 12345);
socket.bind(localEndpoint);
receive(socket, ioContext);
ioContext.run();
return 0;
}
当我把它做成一个类时,计时器永远不会响。使用该类时,主文件的代码如下所示:
#include "udp_class.h"
#include <iostream>
#include <boost/asio.hpp>
int main() {
boost::asio::io_context ioContext;
Proxy my_proxy(ioContext);
my_proxy.start();
ioContext.run();
return 0;
}
类定义为
#pragma once
#define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <iostream>
#include <boost/asio.hpp>
#include <chrono>
using namespace boost::asio;
using ip::udp;
using std::chrono::milliseconds;
class Proxy {
public:
Proxy(io_context& ioContext): localSocket_(ioContext) { };
void start() {
localSocket_.open(udp::v4());
localSocket_.bind(udp::endpoint(ip::address::from_string("127.0.0.1"), 12345));
receive();
};
private:
void receive() {
udp::endpoint receive_endpoint;
std::array<char, 8192> buf;
localSocket_.async_receive_from(buffer(buf, buf.size()), receive_endpoint,
[&](const boost::system::error_code& error, std::size_t bytesReceived) {
if (!error && bytesReceived > 0) {
std::cout << "Got a package" << std::endl;
boost::asio::steady_timer timer = boost::asio::steady_timer(ioContext, boost::asio::chrono::milliseconds(100));
timer.async_wait([&](const boost::system::error_code& ec) {
std::cout << "Timer hit" << std::endl;
});
receive();
} else {
std::cout << "Error receiving data from client" << std::endl;
}
});
}
io_context ioContext;
udp::socket localSocket_;
};
这会接收到一个数据报,注意到控制台,但计时器永远不会命中。
boost asio调试的输出如下所示:
@asio|1720035449.638484|0*1|[email protected]_receive_from
@asio|1720035449.638495|.1|non_blocking_recvfrom,ec=system:35,bytes_transferred=0
@asio|1720035451.692791|.1|non_blocking_recvfrom,ec=system:0,bytes_transferred=12
@asio|1720035451.692827|>1|ec=system:0,bytes_transferred=12
@asio|1720035451.692951|1*2|[email protected]_wait
@asio|1720035451.692976|1*3|[email protected]_receive_from
@asio|1720035451.692987|.3|non_blocking_recvfrom,ec=system:35,bytes_transferred=0
@asio|1720035451.692992|1|[email protected]
@asio|1720035451.692998|<1|
我已经被这个和类似的问题困扰了几天,我真的无法理解我做错了什么。我提取了我的整个代码,并提炼出这个例子,希望它能尽可能简洁地代表问题所在。