• 2546阅读
  • 14回复

[提问]请教关于QTCPServer和QTcpSocket的问题 [复制链接]

上一主题 下一主题
离线clickto
 

只看楼主 倒序阅读 楼主  发表于: 2021-01-10
我一个简单的应用,就一个QTcpServer和一个QTcpSocket进行通信,很简单很常规的流程。
现在出现这样一个问题,即客户端连接上服务器后,是可以正常发送数据给服务器的,可以接受服务器返回的数据。
但是,如果我几分钟(5分钟)不给服务器传数据,之后不管客户端在怎么发送数据,服务器总是接收不到。。。
但是如果隔一段时间发一次数据(小于5分钟),是可以的一直通信的。
通信中断后,主动断开客户端,服务器也接收不到相应的消息,查看服务器的socket状态,一切正常。
而且客户端重启连接的话,仍然可以连接,收发数据。但是一旦再过几分钟,就又挂了。。
请教一下这是怎么回事,如何解决?
服务器是一个控制台应用,跟这个有关系么?
在线20091001753

只看该作者 1楼 发表于: 2021-01-10
你自己要设计一个心跳规则

比如每隔几秒,向服务端发送一个数据,并且服务端也返回一个数据。
这样有2个好处,首先是使得连接保持活跃的状态,然后是可以测试出耗时。

例如规则可以是:你向服务器发送一个时间x,服务器再返回x
那么你就用收到服务器返回的时间减去x,就是通讯的耗时。

另外,如果在x发出1秒后,还没有收到服务器返回的x,那么就可能断了,或是网络非常糟糕。

(づ ̄ 3 ̄)づ
离线clickto

只看该作者 2楼 发表于: 2021-01-10
谢谢版主回答。不过,我只能采用心跳保活么?我之前多次使用QTcpSocket和QTcpServer,都是长连接,都没出现这种问题。
在线20091001753

只看该作者 3楼 发表于: 2021-01-11
客户端与服务端通信,中间会经过非常多的关网,如果你不采用心跳保持稳定的通讯,遇到一些规则严格的网关,就会掐断。
(づ ̄ 3 ̄)づ
离线clickto

只看该作者 4楼 发表于: 2021-01-12
好的,那我加入心跳机制吧。
再次感谢版主大大!!!
离线海森堡

只看该作者 5楼 发表于: 2021-01-12
回 20091001753 的帖子
20091001753:你自己要设计一个心跳规则
比如每隔几秒,向服务端发送一个数据,并且服务端也返回一个数据。
这样有2个好处,首先是使得连接保持活跃的状态,然后是可以测试出耗时。
....... (2021-01-10 19:34) 

请问这个过程中,是QTcpServer产生了timeout无法发送信息,还是QTcpServer产生了timeout无法接收信息呢?它们的默认timeout分别是多少呢?我在文档上找到的信息,都是关于connect的timeout,没有说一段时间不用以后,多久会断开。
在线20091001753

只看该作者 6楼 发表于: 2021-01-13
回 海森堡 的帖子
海森堡:请问这个过程中,是QTcpServer产生了timeout无法发送信息,还是QTcpServer产生了timeout无法接收信息呢?它们的默认timeout分别是多少呢?我在文档上找到的信息,都是关于connect的timeout,没有说一段时间不用以后,多久会断开。 (2021-01-12 21:26) 

客户端与服务端通讯,是2个QTcpSocket通讯,区别在于服务端还有一个QTcpServer用于监听端口。
在这个过程中,服务端的 QTcpSocket 是由 QTcpServer 创建的,并不涉及到 timeout
(づ ̄ 3 ̄)づ
离线clickto

只看该作者 7楼 发表于: 2021-01-13
回 海森堡 的帖子
海森堡:请问这个过程中,是QTcpServer产生了timeout无法发送信息,还是QTcpServer产生了timeout无法接收信息呢?它们的默认timeout分别是多少呢?我在文档上找到的信息,都是关于connect的timeout,没有说一段时间不用以后,多久会断开。 (2021-01-12 21:26)

实测,我遇到的这种中断,并不是确定的timeout或者其他的连接断开。因为如果是连接断开的话,两个socket的state会有变化,同时也会发生disconnect信号。但是我这种情况并没有上述现象发生,查看服务器和客户端的两个socket,都是联通状态,但是过一段时间没有通信后,可以看到客户端确实发送了请求数据,但是服务器端并没有接受到数据。应该就像版主说的,被网关截断了。
离线onlyone

只看该作者 8楼 发表于: 2021-01-14
看你的描述,是1个socket监听,4个tcp客户端连接。要注意如下关键点:

1)模型是用的slect机制吗,阻塞还是异步。qt默认是使用信号曹的异步机制的。如果是异步,则自己要及时读取消息,或者干脆消息不满足则啥也不读,等满足完整报文再处理。

2)网络封包,需要有一套格式,不能乱收,比如先收头部,头部有报文的整体长度,等全部数据长度过来,再接受,否则等第二次信号。

3)多线程的问题。看看网络是不是io很大,如果很大,则是不是有网络io阻塞问题。这样必须换带宽更大的路由器。如果是单线程处理不过来,cpu反应慢,需要考虑多线程编程。

可能的问题很多。但是我觉得,还是你编程错误导致的,或者Ip冲突等低级错误。

离线海森堡

只看该作者 9楼 发表于: 2021-01-14
回 clickto 的帖子
clickto:实测,我遇到的这种中断,并不是确定的timeout或者其他的连接断开。因为如果是连接断开的话,两个socket的state会有变化,同时也会发生disconnect信号。但是我这种情况并没有上述现象发生,查看服务器和客户端的两个socket,都是联通状态,但是过一段时间没有通信后,可以看到客 .. (2021-01-13 20:54)

你这个信息很关键,证实了我的推测。在你不直接做相关设置的情况下(使用setsockopt),其实QTcpSocket本身不用管timeout的问题,而是由系统来控制的。
我估计其实是注册表来控制超时时间,参考文章:
https://blog.csdn.net/libaineu2004/article/details/49054261
离线海森堡

只看该作者 10楼 发表于: 2021-01-14
>>应该就像版主说的,被网关截断了。
这句话我不同意,我认为是被OS截断了。当然网关截断也有可能,但比较小。
离线海森堡

只看该作者 11楼 发表于: 2021-01-14
回 clickto 的帖子
clickto:实测,我遇到的这种中断,并不是确定的timeout或者其他的连接断开。因为如果是连接断开的话,两个socket的state会有变化,同时也会发生disconnect信号。但是我这种情况并没有上述现象发生,查看服务器和客户端的两个socket,都是联通状态,但是过一段时间没有通信后,可以看到客 .. (2021-01-13 20:54) 

麻烦您再做一个测试,client server都在本机上,这样就不需要网关了,看看问题会不会重现?
离线clickto

只看该作者 12楼 发表于: 2021-01-14
回 海森堡 的帖子
海森堡:麻烦您再做一个测试,client server都在本机上,这样就不需要网关了,看看问题会不会重现? (2021-01-14 19:37)

本机或局域网的话,都不存在这种现象,只有在使用公网,即中间通过网关后才有这种现象。
因为我们之前都是做局域网的项目,没遇到过这种现象,这是第一次将服务器部署到云服务器,测试时因为时间间隔短,没发现这个问题,是偶尔一次间隔时间长了,才发现这个现象的。
离线clickto

只看该作者 13楼 发表于: 2021-01-14
另外报告一下,采用了版主的建议,每分钟发送一个心跳包,目前运行没有问题。
离线fsu0413

只看该作者 14楼 发表于: 2021-01-25
反正我之前在做太阳神三国杀的时候遇到这个问题
当时就是用心跳解决的,忘记了用的是多少秒的了,反正不超过半分钟

Note:你永远不知道ISP对你的网络做了什么,所以你一定要做好自己的程序,避免被ISP截胡
快速回复
限100 字节
 
上一个 下一个