boost::asio を使用して TCP および UDP パケットの異なるポートをリッスンするアプリケーションに取り組んでいます。asioチュートリアルの例と同様のサーバークラスを使用してこれを行い、それらすべてを単一のio_serviceに向けました。
したがって、全体として、私の主な機能 (win32 コンソール アプリケーション) は次のようになります。
int main(int argc, char* argv[])
{
//some initializations here
try
{
asio::io_service io_service;
TcpServer ServerTCP_1(io_service, /*port number here*/);
TcpServer ServerTCP_2(io_service, /*port number here*/);
UdpServer ServerUDP(io_service, /*port number here*/);
io_service.run();
}
catch(std::exception& e)
{
std::cerr << e.what() << std::endl;
}
//cleanup code here
return 0;
}
signal_set
また、終了信号が入ったときにアクティブになる非同期操作を実行するために a が使用される HTTP サーバーの例も読みました (これもサーバー クラスに実装しました)。
これが私のTcpServer
クラスです:
class TcpServer : private noncopyable
{
public:
TcpServer(asio::io_service& io_service, int port) :
acceptor_(io_service, tcp::endpoint(tcp::v4(), port)),
signals_(io_service), context_(asio::ssl::context::sslv3)
{
SSL_CTX_set_cipher_list(context_.native_handle(), "ALL");
SSL_CTX_set_options(context_.native_handle(), SSL_OP_ALL);
SSL_CTX_use_certificate_ASN1(context_.native_handle(), sizeof(SSL_CERT_X509), SSL_CERT_X509);
SSL_CTX_use_PrivateKey_ASN1(EVP_PKEY_RSA, context_.native_handle(), SSL_CERT_RSA, sizeof(SSL_CERT_RSA));
SSL_CTX_set_verify_depth(context_.native_handle(), 1);
signals_.add(SIGINT);
signals_.add(SIGTERM);
signals_.add(SIGBREAK);
#if defined(SIGQUIT)
signals_.add(SIGQUIT);
#endif // defined(SIGQUIT)
signals_.async_wait(boost::bind(&TcpServer::handle_stop, this));
start_accept();
}
private:
tcp::acceptor acceptor_;
asio::ssl::context context_;
asio::signal_set signals_;
TcpConnection::pointer new_ssl_connection;
void start_accept(){
new_ssl_connection.reset(new TcpConnection(acceptor_.get_io_service(), context_));
acceptor_.async_accept( new_ssl_connection->socket(),
boost::bind(&TcpServer::handle_acceptSSL, this, asio::placeholders::error));
}
void handle_acceptSSL(const system::error_code& error){
if(!error)
new_ssl_connection->start();
start_accept();
}
void handle_stop(){
acceptor_.close();
printf("acceptor closed");
}
};
今私は3つの異なるサーバーオブジェクトを持っているので、彼はそれらのすべてのアクセプターを閉じる必要がありio_service
ます. それに加えて、呼び出しも3回実行する必要がありますか?io_service
run()
printf
まず第一にio_service
、クリーンアップコードに到達することはありません。第 2 に、コンソールに表示される printf 呼び出しは多くても 1 つだけです。
そして第三に、いくつかのデバッグを行うことで、プログラムを終了するhandle_stop()
と が一度呼び出されることがわかりましたが、何らかの理由でプログラムがハンドルのどこかで閉じます (つまり、ときどき彼は printf に到達してその後閉じ、ときどきただ取得するだけです)。へacceptor_.close()
)
言及する価値があるかもしれないもう1つのことは、プログラムがクローズ後に0を返さず、代わりにこれを返すことです(スレッドの数は異なります):
The thread 'Win32 Thread' (0x1758) has exited with code 2 (0x2).
The thread 'Win32 Thread' (0x17e8) has exited with code -1073741510 (0xc000013a).
The thread 'Win32 Thread' (0x1034) has exited with code -1073741510 (0xc000013a).
The program '[5924] Server.exe: Native' has exited with code -1073741510 (0xc000013a).
なぜこれが起こっているのか、どうすれば修正できるのか、どうすればクリーンアップコードに正しくアクセスできるのかを知りたいです。