- 平台:Windows 7 Professional 64 位
- 编译器:VS2010 Express
- 提升:版本 1.49
- 插件系统:OBSE 20(用于 Bethesda 的 Oblivion 游戏)
我有一个基于异步 udp 示例的类。我将 io 服务本身作为线程运行。这是该类的代码:
// udp buffer queues
extern concurrent_queue<udp_packet> udp_input_queue; // input from external processes
extern concurrent_queue<udp_packet> udp_output_queue; // output to external processes
using boost::asio::ip::udp;
class udp_server
{
public:
udp_server(boost::asio::io_service& io_service, short port)
: io_service_(io_service),
socket_(io_service_, udp::endpoint(boost::asio::ip::address_v4::from_string(current_address), port))//, // udp::v4()
{
// start udp receive
socket_.async_receive_from(
boost::asio::buffer(recv_buf), sender_endpoint_,
boost::bind(&udp_server::handle_receive_from, this,
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred));
send_timer_ = NULL;
}
~udp_server(){
io_service_.stop();
if(send_timer_){
send_timer_->cancel();
delete send_timer_;
}
}
void start(){
// start send timer
send_timer_ = new boost::asio::deadline_timer(io_service_, boost::posix_time::milliseconds(500));
send_timer_restart();
}
void handle_send_to(const boost::system::error_code& error, size_t bytes_recvd);
void handle_receive_from(const boost::system::error_code& error, size_t bytes_recvd);
//void handle_send_timer(const boost::system::error_code& error);
void handle_send_timer();
void send_timer_restart();
void stop()
{
io_service_.stop();
}
private:
boost::asio::io_service& io_service_;
udp::socket socket_;
udp::endpoint sender_endpoint_;
std::vector<udp::endpoint> clientList;
//std::auto_ptr<boost::asio::io_service::work> busy_work;
udp_buffer recv_buf;
boost::asio::deadline_timer* send_timer_;
};
现在我像这样实例化类和线程:
udp_server *udp_server_ptr=NULL;
boost::asio::deadline_timer* dlineTimer=NULL;
static void PluginInit_PostLoadCallback()
{
_MESSAGE("NetworkPipe: PluginInit_PostLoadCallback called");
if(!g_Interface->isEditor)
{
_MESSAGE("NetworkPipe: Starting UDP");
udp_server_ptr = new udp_server(io_service, current_port);
//dlineTimer = new boost::asio::deadline_timer(io_service);
udp_thread = new boost::thread(boost::bind(&boost::asio::io_service::run, &io_service));
//
_MESSAGE("NetworkPipe: UDP Started");
NetworkPipeEnable = true;
}
else
{
_MESSAGE("NetworkPipe: Running in editor, not starting UDP");
}
}
现在注意 dlineTimer 在上面被注释掉了。如果我启用它,它将停止运行。我可以让 dlineTimer 与此 io 服务一起运行的唯一方法是在udp_server::handle_receive_from
调用期间创建它。我认为这是因为它在另一个线程内运行。所以由于某种原因,deadline_timer
对象不喜欢在它需要在内部运行的线程之外创建。
现在,为了与主线程通信,我使用concurrent_queue
对象。所以这些让我可以非常简单地在线程中发送消息。理论上我可以dlineTimer
在它自己的线程内部运行并使用输出队列来管理它的活动。但是,我喜欢与udp_server
. 例如,udp_server
对象在向量中跟踪客户端。当deadline_timer
到期时,我会循环访问已知的客户端并向他们发送消息。然后我重新启动计时器。这使得我的响应独立于发送到服务器的 udp 数据包。因此,当数据包到达时,它们会被放入队列中,等待处理的另一部分。然后将后面的数据放在输出队列中,然后deadline_timer
处理这些响应并将它们发送给适当的客户端。
所以我的主要问题是:
如何deadline_timer
使用与对象相同的线程io_service
更干净地创建udp_server
对象?