广域网TCP通讯,客户端关闭连接服务器端没反应?

时间:2022-11-27 20:06:33
写了个TCP通讯的测试程序,服务器端采用IOCP的模式编写,客户端采用普通tcp client。
在局域网运行的时候,客户端关闭socket时,服务器端的 GetQueuedCompletionStatus都会从阻塞中返回,然后读到0字节数据,就知道客户端关闭连接了。

但是我在一台ADSL拨号的PC上运行服务器(在路由器上做了端口映射),客户端连接、收发数据都没什么问题,但是关闭socket的时候,服务器端却没有任何反映。

求教这是什么原因造成的?请问应该怎样才能让服务器端得知客户端主动断开连接?

9 个解决方案

#1


外网情况很复杂。。有时服务端是收不到客户端断开的消息的。

#2


呃,这个是测试了好多次都收不到。
有没什么方法可以尽快通知服务器端客户端断开连接的?(倒是考虑了用心跳包的方法,但是想的是对应非正常断开的,没办法收到正常断开信息吗)

#3


那就自己定一个断开连接的消息,客户端主动发送给服务端,服务端收到后,就断开连接

#4


不管什么情况下,服务器端需要有定时检测机制,因为还有些情况下服务器端也是收不到断开消息的(比如拔网线和意外宕机)

#5


引用 3 楼 oyljerry 的回复:
那就自己定一个断开连接的消息,客户端主动发送给服务端,服务端收到后,就断开连接


嗯,这倒是个办法。

#6


引用 4 楼 shenyi0106 的回复:
不管什么情况下,服务器端需要有定时检测机制,因为还有些情况下服务器端也是收不到断开消息的(比如拔网线和意外宕机)


这个倒是考虑了,用心跳数据包加定时器检测的方法实现了。

#7


引用楼主 zhaokai3000 的回复:
写了个TCP通讯的测试程序,服务器端采用IOCP的模式编写,客户端采用普通tcp client。
在局域网运行的时候,客户端关闭socket时,服务器端的 GetQueuedCompletionStatus都会从阻塞中返回,然后读到0字节数据,就知道客户端关闭连接了。

但是我在一台ADSL拨号的PC上运行服务器(在路由器上做了端口映射),客户端连接、收发数据都没什么问题,但是关闭socke……

你可以用抓包工具看看ADSL正常断开的时候,发了Fin包了没有,你的服务器端接收了这个Fin包了没有,可以看下关闭的过程

#8


心跳随时都是必须的

#9


定义心跳协议
在没有数据的时候,客户端每N秒发心跳给服务器,服务器要回复ack给发心跳的客户端。没问题就是没掉线,
如果服务器N秒没回ACK给客户端,客户端继续发,定义发几次都没回ack的话,客户端认为服务器和客户端断开连接。
服务器给每个客户端记录时间,每次判断如果当前时间距离上次客户端发包N秒内没有数据过来则断开和此客户端连接。

#1


外网情况很复杂。。有时服务端是收不到客户端断开的消息的。

#2


呃,这个是测试了好多次都收不到。
有没什么方法可以尽快通知服务器端客户端断开连接的?(倒是考虑了用心跳包的方法,但是想的是对应非正常断开的,没办法收到正常断开信息吗)

#3


那就自己定一个断开连接的消息,客户端主动发送给服务端,服务端收到后,就断开连接

#4


不管什么情况下,服务器端需要有定时检测机制,因为还有些情况下服务器端也是收不到断开消息的(比如拔网线和意外宕机)

#5


引用 3 楼 oyljerry 的回复:
那就自己定一个断开连接的消息,客户端主动发送给服务端,服务端收到后,就断开连接


嗯,这倒是个办法。

#6


引用 4 楼 shenyi0106 的回复:
不管什么情况下,服务器端需要有定时检测机制,因为还有些情况下服务器端也是收不到断开消息的(比如拔网线和意外宕机)


这个倒是考虑了,用心跳数据包加定时器检测的方法实现了。

#7


引用楼主 zhaokai3000 的回复:
写了个TCP通讯的测试程序,服务器端采用IOCP的模式编写,客户端采用普通tcp client。
在局域网运行的时候,客户端关闭socket时,服务器端的 GetQueuedCompletionStatus都会从阻塞中返回,然后读到0字节数据,就知道客户端关闭连接了。

但是我在一台ADSL拨号的PC上运行服务器(在路由器上做了端口映射),客户端连接、收发数据都没什么问题,但是关闭socke……

你可以用抓包工具看看ADSL正常断开的时候,发了Fin包了没有,你的服务器端接收了这个Fin包了没有,可以看下关闭的过程

#8


心跳随时都是必须的

#9


定义心跳协议
在没有数据的时候,客户端每N秒发心跳给服务器,服务器要回复ack给发心跳的客户端。没问题就是没掉线,
如果服务器N秒没回ACK给客户端,客户端继续发,定义发几次都没回ack的话,客户端认为服务器和客户端断开连接。
服务器给每个客户端记录时间,每次判断如果当前时间距离上次客户端发包N秒内没有数据过来则断开和此客户端连接。