解决socket连接超时问题

最近两天 项目其中一台IM服务器的IM验证出现问题,进行用户IM注册时出现连接超时问题;

重启服务后,可以进行用户的IM注册验证,没有出现超时问题;但是等到半个钟一个钟(时间不定);

结果还是会有连接超时问题,所有单单是重启解决不了问题,也不可能一有问题就去重启服务

问题一:

登录服务器后台,使用netstat -ant命令查看当前网络状态:(此图是禁用IPV6后截图)
《解决socket连接超时问题》

发现,输出中没有IM验证绑定的端口9193;但服务却是在运行;

然后使用 lsof -i:9193 能够获取到打开的文件记录,说明端口是启动的 ;但是,记录中的type是IPV6

猜测是否是因为使用了IPV6连接方式导致的问题,然后逐一测试80,8080等端口,发现凡是IPV6连接方式都不会显示

接下来,选择禁用IPV6:

打开/etc/sysctl.conf

在文件末尾添加:

禁用整个系统所有接口的IPv6

net.ipv6.conf.all.disable_ipv6 = 1
  # 禁用某一个指定接口的IPv6(例如:eth0, lo)
  net.ipv6.conf.lo.disable_ipv6 = 1
  net.ipv6.conf.eth0.disable_ipv6 = 1
  在 /etc/sysctl.conf 使这些更改生效,运行以下命令:
  $ sudo sysctl -p /etc/sysctl.conf
  或者直接重启。

问题二:

解决上述问题后,重启服务后,连接超时异常还是出现;

使用netstat -ant查看连接状态,出现close_wait 状态;该问题是由于服务端或者

客户端其中某一方手动关闭了连接,服务端没有收到断开连接的请求,所以报错;

只能去查看源码:

查看源码,发现客户端和服务端的socket源码,都没有写异常的处理方式;

然后修改server源码,在异常中加上判断:(客户端的socket请求一样添加了处理)

1.判断socket是否为空

2.判断socket是否关闭 (使用isClosed())

3.手动关闭未关闭的socket

打包升级服务端后,客户端连接注册,问题解决

来自网络:

SOCKET CLOSE_WAIT状态的说明:
CLOSE_WAIT出现的原因: 就是某一方在网络连接断开后,对等方没有检测到这个错误(对方断开)而没有调用 closesocket,导致了这个状态的出现;

断开连接的时候:
当发起主动关闭的左边这方发送一个FIN过去后,右边被动关闭的这方要回应一个ACK,
这个ACK是TCP回应的(同时TCP向上层应用程序提交一个ERROR,导致上面的SOCKET的send
或者recv返回SOCKET_ERROR),而不是应用程序发送的,此时,被动关闭的一方就处于
CLOSE_WAIT状态了。如果此时被动关闭的这一方不再继续调用closesocket,
那么他就不会发送接下来的FIN,导致自己老是处于CLOSE_WAIT。只有被动关闭的这一方
调用了closesocket,才会发送一个FIN给主动关闭的这一方,同时也使得自己的状态变迁
为LAST_ACK,待接收到主动关闭方发送的ACK后,才会将SOCKET置为CLOSED。

首先我们知道,如果我们的Client程序处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!
因为如果是Server端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet:
Server —> FIN —> Client
Server <— ACK <— Client
这时候Server端处于FIN_WAIT_2状态;而我们的程序处于CLOSE_WAIT状态。
Server <— FIN <— Client
这时Client发送FIN给Server,Client就置为LAST_ACK状态。
Server —> ACK —> Client
Server回应了ACK,那么Client的套接字才会真正置为CLOSED状态。

转载:https://blog.csdn.net/qq_33571718/article/details/78508735

    原文作者:leaf13
    原文地址: https://blog.csdn.net/leaf13/article/details/102621955
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞