C++ 正确终止boost::asio::ip::tcp::accept(Linux)

C++ 正确终止boost::asio::ip::tcp::accept(Linux),c++,boost,synchronous,C++,Boost,Synchronous,我想知道如何使用boost实现一个可以终止的同步套接字accept 为了证明我的问题,我稍微修改了 注意:提供的代码似乎在Windows平台上运行,但我在Linux机器上遇到问题 假设服务器收到一条退出消息,现在想要终止一个接受新连接的无止境循环。 大多数教程等都建议您在这种情况下运行acceptor->close()。但作为 状态,如果从另一个线程调用close(),则结果可能未定义 如果您这样做,accept()这次不会终止,但当另一个客户端尝试连接时,它会返回一个错误(在Linux上!)

我想知道如何使用boost实现一个可以终止的同步套接字accept

为了证明我的问题,我稍微修改了

注意:提供的代码似乎在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;
}
#包括
#包括
#包括
#包括
#包括
#包括
使用boost::asio::ip::tcp;
无效会话(boost::shared_ptr sock,tcp::acceptor*acceptor)
{
试一试{
对于(;;){
字符数据[1024];
boost::system::error\u code error;
size\u t length=sock->read\u some(boost::asio::buffer(data),错误);
if(error==boost::asio::error::eof){break;}
else if(error){throw boost::system::system_error(error);}
如果(std::string(“quit”)==data){//请尝试取消接受
接受者->关闭();
打破
}
boost::asio::write(*sock,boost::asio::buffer(数据,长度));
}
}

catch(std::exception&e){std::cerr我不知道从
boost::asio
中取消同步
accept
的方法。你能将其重构为使用
async_accept()
吗?(答案当然是肯定的——但如果你的实际代码不是像本例中那样微不足道的话,这可能是一些工作)。是的。你为什么要进行阻塞套接字调用?要体验线程应用程序的恐怖,以增加尝试取消同步操作的乐趣?当然要使用非阻塞套接字。如果你坚持,你需要在accept()调用上设置计时器(例如sigallarm)并在每个循环中检查一个标志。50ms警报意味着主线程在处理取消之前不必等待超过50ms。