南京百度网站建设,大学生创新创业点子,金蝶软件做账全过程,seo搜索引擎优化入门问题场景
在使用 QT 开发一个客户端 App 的时候#xff0c;我们通过 QTcpSocket 与后台服务器进程通信。 后台程序使用其他语言编写。 问题#xff1a; 在客户端启用之后尝试建立与后台程序的 TCP 连接的时候#xff0c;发现连接速度非常慢#xff08;肉眼可见的慢#x…问题场景
在使用 QT 开发一个客户端 App 的时候我们通过 QTcpSocket 与后台服务器进程通信。 后台程序使用其他语言编写。 问题 在客户端启用之后尝试建立与后台程序的 TCP 连接的时候发现连接速度非常慢肉眼可见的慢。
我的客户端代码
...
m_Socket new QTcpSocket();
m_RemoteHost 0.0.0.0;
m_RemotePort 20021;m_Socket-connectToHost(m_RemoteHost, m_RemotePort);
if (!m_Socket-waitForConnected(5000)) {// error
}
...问题分析
根据本人从事网络开发的经验来看对于建立一个 TCP 连接即使服务器在公网在服务器压力正常的情况下连接时间应处于 50ms-100ms。 此时我们的服务器还是处于同一局域网中且当前并没有其他连接 因此怀疑问题出在 QTcpSocket 上。服务器做过单独的测试连接速度没有问题
没有尝试获取 QTcpSocket 的日志直接使用 Wireshark 抓包看看导致是慢在了哪里
抓的包如下图 嗬就淡看这么多的红色记录不慢才怪了下来我们仔细看看问题的原因
10 条红色记录分别是 5 次我们发送的 TCP SYN 被拒绝服务器响应 TCP RST的记录。
服务器为什么拒绝我们的连接请求
点开我们的第一个 SYN 包详细结构如下 这里看到TCP 包没有任何问题。 问题在于 IP 包我们客户端使用的 IPv6. 额好吧 QTcpSocket 默认竟然使用的 IPv6. 而我们的服务器只监听在了 IPv4 的端口 因此连接无法建立服务器选择 reset 我们的连接。
在看 log 发现 QTcpSocket 在初次连接失败之后没有直接回退到 IPv4 协议而是选择了重试。从图中我们也能看到它重试了五次. 再进一步我们可以看出每次重试的间隔为 500ms. 额滴天就重试这五次花费了 2s 时间。
在 5 次重试之后QTcpSocket 选择回退到 IPv4 之后连接成功.
由 wireshark log 可以看到我们当前环境下一个正常的 TCP 连接需要时间是 14.714993 - 14.714753 0.000240s, 也就是说在 1ms 级别我的测试服务器和客户端在一台机器 硬生生的被拖延到 2s.
如何修改代码
...
m_Socket new QTcpSocket();
m_RemoteHost 0.0.0.0;
m_RemotePort 20021;// 指定使用 IPv4
m_Socket-connectToHost(m_RemoteHost, m_RemotePort, QAbstractSocket::ReadWrite, QAbstractSocket::IPv4Protocol);
if (!m_Socket-waitForConnected(5000)) {// error
}
...问题非常简单却让人比较经验竟然默认使用的 IPv6。 IPv6 已经这么流行了吗 竟然至于默认使用 IPv6 协议。 佩服佩服啊