Winsock 连接很慢

Posted

技术标签:

【中文标题】Winsock 连接很慢【英文标题】:Winsock connect is slow 【发布时间】:2021-10-27 15:06:44 【问题描述】:

我有一个程序使用 Boost.Asio 连接到本地主机上的服务器。这是代码的相关部分:

TcpClient::TcpClient(uint16_t port_number) : socket_(service_)

    boost::asio::ip::tcp::resolver resolver(service_);
    boost::asio::ip::tcp::resolver::query resolver_query("localhost", std::to_string(port_number));
    auto endpoint_iterator = resolver.resolve(resolver_query);
    boost::asio::connect(socket_, endpoint_iterator);

代码功能很好。在 Ubuntu 上,connect 函数几乎立即返回。但是,在 Windows 上,完成需要超过 2 秒。

单步执行 boost 代码,我发现这 2 秒都花在了 Winsock connect 函数调用上。

我是否遗漏了一些可以加快调用速度的东西(无论是在代码中还是在环境中)?

谢谢!

【问题讨论】:

我通常的嫌疑人是Nagle's algorithm。嗯,在这种情况下可能不是嫌疑人。 @Eljay AFAIK Nagle 不适用于connect(),仅适用于send() 可能与 IPv6 有关。检查resolver.resolve 返回的地址。还有,端口和服务器是什么? 延迟 Acks (TCP_QUICKACK) 可能有问题? 我的猜测是localhost 可能返回一个 ipv4 和 ipv6 地址,首先尝试 ipv6 地址,然后在错误/超时后尝试 ipv4。 【参考方案1】:

如果您启用了 IPv6,则resolver_query("localhost", std::to_string(port_number)); 将返回 IPv4 和 IPv6 地址(根据首先列出的 IPv6 的经验)。如果您的服务器没有监听 IPv6,那么boost::asio::connect 将首先尝试 IPv6,等待它失败,然后再尝试 IPv4。

要么让你的服务器监听 IPv6,使用“127.0.0.1”而不是 localhost,要么限制解析器只返回 IPv4:

resolver_query(boost::asio::ip::tcp::v4(), "localhost", std::to_string(port_number));

【讨论】:

专业提示:将127.0.0.1 localhost 添加到hosts 文件中,以后再也不用担心这个问题了。

以上是关于Winsock 连接很慢的主要内容,如果未能解决你的问题,请参考以下文章

Python Winsock - 如何通过已经处于活动状态的 Winsock 连接发送数据

C#中的WINSOCK连接

winsock 连接功能仅适用于高速连接

Winsock - 停止接受新连接但与现有连接保持通信

Winsock - 客户端断开连接,关闭套接字循环/最大连接数

winsock 客户端反复尝试连接服务器