私は、ブーストASIOとコルーチンを使って安全なSSLエコーサーバを作成しています。理論的にはio_serviceマネージャに制御を戻しますasync_acceptを呼び出す:私は、このサーバーは、同時に複数のクライアントにサービスを提供できるようにしたいのですが、これは、私は上記のコードがどうなるかはわからない。とにかく私のコードasync_acceptで複数のクライアントを扱う
try {
boost::asio::io_service io_service;
boost::asio::spawn(io_service, [&io_service](boost::asio::yield_context yield) {
auto ctx = boost::asio::ssl::context{ boost::asio::ssl::context::sslv23 };
ctx.set_options(
boost::asio::ssl::context::default_workarounds
| boost::asio::ssl::context::no_sslv2
| boost::asio::ssl::context::single_dh_use);
ctx.use_private_key_file(..); // My data setup
ctx.use_certificate_chain_file(...); // My data setup
boost::asio::ip::tcp::acceptor acceptor(io_service,
boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), port));
for (;;) {
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sock{ io_service, ctx };
acceptor.async_accept(sock.next_layer(), yield);
sock.async_handshake(boost::asio::ssl::stream_base::server, yield);
auto ec = boost::system::error_code{};
char data_[1024];
auto nread = sock.async_read_some(boost::asio::buffer(data_, 1024), yield[ec]);
if (ec == boost::asio::error::eof)
return; //connection closed cleanly by peer
else if (ec)
throw boost::system::system_error(ec); //some other error, is this desirable?
sock.async_write_some(boost::asio::buffer(data_, nread), yield[ec]);
if (ec == boost::asio::error::eof)
return; //connection closed cleanly by peer
else if (ec)
throw boost::system::system_error(ec); //some other error
// Shutdown gracefully
sock.async_shutdown(yield[ec]);
if (ec && (ec.category() == boost::asio::error::get_ssl_category())
&& (SSL_R_PROTOCOL_IS_SHUTDOWN == ERR_GET_REASON(ec.value())))
{
sock.lowest_layer().close();
}
}
});
io_service.run();
}
catch (std::exception& e)
{
std::cerr << "Exception: " << e.what() << "\n";
}
です。
既に受け入れられている、つまりすでにasync_accept行を過ぎている場合、別の接続を受け入れることができますか?
これはコルーチンを使用していることに注意することが重要です。これは典型的な使用例ではありません(まだ)。それは生涯の構造を劇的に変えます。特に、stackfulコルーチン – sehe
Haを使用しない限り、ソケットのローカル変数で 'async_accept'を使うことは大きな問題です。私は次回のタイトルを超えて質問を読むべきです:)私は少し速い答えにスキップしました。 (私は通常、ソケットを 'session'のメンバにするので、両方の方法で使いやすいです)。 +1 – sehe
ありがとう、このコードはちょうどmain()ルーチンにあります。私もそれを投稿しておくべきだった、申し訳ありません。私のコードが動作するかどうかはまだ分かりません:リンクした例の 'go'関数のように別の' boost :: spawn'を呼び出さなければなりませんか?これらはスレッドではなく、私は混乱しています..着信接続はバッファされていますか? 2番目のコルーチンを生成すると、他の接続を処理できますか? – Dean