提振.asio client/server TIME_WAIT原因



我正在尝试运行一些功能测试到一些API。

我的API有一个客户端和一个服务器端。客户端只是连接并设置一个标志。服务器只接受连接。

这是一个测试用例:

BOOST_AUTO_TEST_CASE(client_can_connect_to_server) {
        boost::asio::io_service serverService;
        std::thread serverLoop([&serverService] { serverService.run(); }); 
        boost::asio::io_service clientService; 
        std::thread clientLoop([&clientService] { clientService.run(); }); 
        //    std::this_thread::sleep_for(10ms); Maybe wait for server loop to start...?

        auto connectionSuccess = connectTo("127.0.0.1", "54321", kAuthData, ioService); 
        BOOST_REQUIRE(blockForDurationOrWhile
                      (timeout,
                       [&] { return connectionSuccess.wait_for(0s) != std::future_status::ready; }) == ExitStatus::ConditionSatisfied);
        serverService.stop();
        clientLoop.join();
        serverService.join();    
    }

我有两个问题:

  1. 连接超时超过一半的时间,但有时工作。
  2. 当通过成功路径完成程序到测试结束时,netstat似乎显示出某种套接字泄漏状态为TIME_WAIT。我正在关闭和关闭插座。我就是不知道哪里出了问题。这显示在应用程序退出后大约30-45秒:

    tcp 0 0 ip6-localhost:52256 ip6-localhost:54321 TIME_WAIT
    tcp 0 0 ip6-localhost:54321 ip6-localhost:52256 TIME_WAIT

客户端和服务器端代码如下:

std::future<bool> connectTo(std::string const & host,
                            std::string const & port,
                            std::string const & authData,
                            boost::asio::io_service & s,
                            std::chrono::high_resolution_clock::duration timeout = kCortexTryConnectTimeout) {
    using namespace boost::asio;
    using boost::asio::ip::tcp;
    std::promise<bool> p;
    auto res = p.get_future();
    spawn
        (s,
         [&s, host, port, p = std::move(p)](yield_context yield) mutable {
            tcp::socket socket(s);
            BOOST_SCOPE_EXIT(&socket) {
                std::cout << "Closing client socketn";
                if (socket.is_open()) {
                    boost::system::error_code ec{};
                    socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                    socket.close();
                    std::cout << "Client socket closedn";
                }
            } BOOST_SCOPE_EXIT_END
            std::cout << "Client trying to connectn";
            tcp::resolver resolver(s);
            boost::system::error_code ec{boost::asio::error::operation_aborted};
            boost::asio::async_connect(socket, resolver.resolve({host, port}), yield[ec]);
            std::cout << "Client Connectedn";
            if (!ec) p.set_value(true);
            else p.set_value(false);
        });
    return res;
}

服务器处理连接:

class ConnectionsAcceptorTask {
public:
    //Session handling for Cortex. Will move out of here
    class Session : public std::enable_shared_from_this<Session> {
    public:
        explicit Session(boost::asio::ip::tcp::socket socket) : _socket(std::move(socket)) {}
        void start() {}
        ~Session() {
            if (_socket.is_open()) {
                boost::system::error_code ec{};
                _socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec);
                _socket.close();
            }
        }
    private:
        boost::asio::ip::tcp::socket _socket;
    };
    ConnectionsAcceptorTask(unsigned int port,
                            io_service & s)
        : _port(port),
          _ioService(&s)
    {}
    void operator()() {
        namespace ba = boost::asio;
        using boost::asio::ip::tcp;
        ba::spawn
            (*_ioService,
             [s = _ioService, port = this->_port](ba::yield_context yield) {
                tcp::acceptor acceptor
                    (*s,
                     tcp::endpoint(tcp::v4(), port));
                acceptor.set_option(boost::asio::socket_base::reuse_address(true));
                BOOST_SCOPE_EXIT(&acceptor) {
                    std::cout << "Closing acceptorn";
                    if (acceptor.is_open()) {
                        acceptor.close();
                        std::cout << "Acceptor closedn";
                    }
                } BOOST_SCOPE_EXIT_END
                for (;;) {
                    boost::system::error_code ec{};
                    tcp::socket socket(*s);
                    acceptor.async_accept(socket, yield[ec]); 
                    if (!ec) std::make_shared<Session>(std::move(socket))->start();
                }
            });
    }
private:
    unsigned int _port = 0;
    boost::asio::io_service * _ioService;
};

TIME_WAIT状态不是套接字泄漏。

是RFC 793中指定的TCP连接断开的正常部分。

相关内容

最新更新