3

我想知道如何使用可以终止的 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;
}
4

0 回答 0