我想知道如何使用可以终止的 boost 实现同步套接字接受。
为了演示我的问题,我稍微修改了同步 tcp echo 示例。
注意:提供的代码似乎可以在 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;
}