終了できるブーストを使用して同期ソケット受け入れを実装する方法を知りたいです。
私の問題を示すために、同期 tcp エコーの例を少し変更しました。
注: 提供されたコードは Windows プラットフォームで動作しているようですが、Linux マシンでは問題が発生しています。
サーバーが終了メッセージを受信し、新しい接続を受け入れる無限ループを終了したいとします。この場合、ほとんどのチュートリアルなどでは、acceptor->close() を実行することをお勧めします。しかし、
この投稿close()
が述べているように、別のスレッドから呼び出された場合、結果は未定義になる可能性があります。
その場合、accept()
今回は終了しませんが、別のクライアントが接続しようとするとエラーが返されます (Linux の場合!)。
もう一度質問しますboost::asio
。接続を継続的に同期的に受け入れることに基づいているサーバーを正しく終了するにはどうすればよいですか?
ここにコード:
#include <cstdlib>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
using boost::asio::ip::tcp;
void session(boost::shared_ptr<tcp::socket> sock, tcp::acceptor *acceptor )
{
try {
for (;;) {
char data[ 1024 ];
boost::system::error_code error;
size_t length = sock->read_some(boost::asio::buffer(data), error);
if (error == boost::asio::error::eof) { break; }
else if (error) { throw boost::system::system_error(error); }
if( std::string("quit") == data ) { // TRY TO CANCEL THE ACCEPT
acceptor->close();
break;
}
boost::asio::write(*sock, boost::asio::buffer(data, length));
}
}
catch (std::exception& e) { std::cerr << "exception in thread: " << e.what() << "\n"; }
}
void server(boost::asio::io_service& io_service, short port)
{
tcp::acceptor a( io_service, tcp::endpoint(tcp::v4(), port) );
for (;;) {
boost::shared_ptr<tcp::socket> sock(new tcp::socket(io_service));
boost::system::error_code error;
a.accept( *sock, error );
if( !error ) {
boost::thread t( boost::bind( session, sock, &a ) );
}
else {
std::cout << "acceptor canceled "<< error << std::endl;
break;
}
}
}
int main(int argc, char* argv[])
{
try{
// ..check args here...
boost::asio::io_service io_service;
server(io_service, std::atoi(argv[1]));
}
catch (std::exception& e) {std::cerr << "Exception: " << e.what() << "\n";}
return 0;
}