外部システムとの UDP 通信を可能にするOrbiter space simulator用の DLL プラグインを作成しています。低レベルのものから抽象化できるため、タスクにboost::asioを選択しました。
「境界条件」は次のとおりです。
- 任意のスレッドを作成したり、DLL から任意の API 関数を呼び出したりできます
- 他のスレッド セーフがないため、DLL (各フレーム) に渡されたコールバック内でのみシミュレーション内のデータを変更できます。
したがって、通信に使用している NetworkClient クラスに次のアーキテクチャを選択しました。
- 構築時に、UDP ソケット (boost::socket+boost::io_service) を初期化し、io_service.run() を呼び出すスレッドを開始します。
- 着信メッセージは非同期でキューに入れられます (CriticalSection によるスレッドセーフ)。
- コールバック処理関数は、キューからメッセージを取得して処理できます
ただし、実装を実行すると奇妙な例外が発生しました: boost::exception_detail::clone_impl > at memory location 0x01ABFA00.
例外は io_service.run() 呼び出しで発生します。
誰か教えてください。私のクラスのコード リストは以下のとおりです。
NetworkClient 宣言:
class NetworkClient {
public:
NetworkClient(udp::endpoint server_endpoint);
~NetworkClient();
void Send(shared_ptr<NetworkMessage> message);
inline bool HasMessages() {return incomingMessages.HasMessages();};
inline shared_ptr<NetworkMessage> GetQueuedMessage() {return incomingMessages.GetQueuedMessage();};
private:
// Network send/receive stuff
boost::asio::io_service io_service;
udp::socket socket;
udp::endpoint server_endpoint;
udp::endpoint remote_endpoint;
boost::array<char, NetworkBufferSize> recv_buffer;
// Queue for incoming messages
NetworkMessageQueue incomingMessages;
void start_receive();
void handle_receive(const boost::system::error_code& error, std::size_t bytes_transferred);
void handle_send(boost::shared_ptr<std::string> /*message*/, const boost::system::error_code& /*error*/, std::size_t /*bytes_transferred*/) {}
void run_service();
NetworkClient(NetworkClient&); // block default copy constructor
};
メソッドの実装:
NetworkClient::NetworkClient(udp::endpoint server_endpoint) : socket(io_service, udp::endpoint(udp::v4(), 28465)) {
this->server_endpoint = server_endpoint;
boost::thread* th = new boost::thread(boost::bind(&NetworkClient::run_service,this));
start_receive();
}
void NetworkClient::start_receive()
{
socket.async_receive_from(boost::asio::buffer(recv_buffer), remote_endpoint,
boost::bind(&NetworkClient::handle_receive, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)
);
}
void NetworkClient::run_service()
{
this->io_service.run();
}