- プラットフォーム: Windows 7 プロフェッショナル 64 ビット
- コンパイラ: VS2010 Express
- ブースト: バージョン 1.49
- Plugin System : OBSE 20 (Bethesda の Oblivion ゲーム用)
async 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 がコメントアウトされていることに注意してください。それを有効にすると、機能しなくなります。この io サービスで dlineTimer を機能させる唯一の方法は、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
ですか?