我有一个使用java.net.Socket与PC无线通信的Android设备。一切都很好,但如果我没有做任何事情(即没有网络使用)正好1分钟,那么当Android向PC发送数据包时,PC会收到它并发送一个ACK,但Android会以RST响应。
来自Wireshark(10.1.2.1是Android,10.1.2.11是PC)......
356 0.112470 10.1.2.1 10.1.2.11 TCP 97 34360→181 [PSH,ACK] Seq = 1 Ack = 1 Win = 4935 Len = 31 TSval = 156103571 TSecr = 320673352
359 0.000011 10.1.2.11 10.1.2.1 TCP 66 181→34360 [ACK] Seq = 1 Ack = 32 Win = 260 Len = 0 TSval = 320738236 TSecr = 156103571
360 0.000304 10.1.2.1 10.1.2.11 TCP 60 34360→181 [RST] Seq = 32 Win = 0 LEN = 0
此时,如果我询问套接字的成员变量,它说。 。 。
...看起来我应该仍然接收数据包就好了。 那我怎么弄清楚为什么我发送RST ?
N.B。 - 没有设置“休眠”或关闭此设备上启用的wifi或显示器或任何其他节电功能设置。
答案 0 :(得分:2)
1分钟的延迟看起来像是超时。它可能是SO_TIMEOUT
,但这不会自己生成网络活动。此外,发送的最后一个数据包包含31个字节的数据似乎表明涉及该应用程序。可能的情况是:
SO_TIMEOUT
触发)setSoLinger(true, 0)
套接字选项。答案 1 :(得分:1)
这些Socket
方法都没有返回连接状态。它们都与java.net.Socket
对象的内部状态有关,这取决于您在其上调用的构造函数和方法。如果对等方断开连接,他们就不会神奇地开始返回false
。
当你去使用套接字获取I / O时,你会发现你将获得IOException: 'connection reset'
。
为什么重置连接是另一回事。通常的原因是您已经发送到已经被对等方关闭的连接,或者对等方关闭了连接而没有读取已经到达的所有数据。换句话说,应用程序协议错误。还有其他原因,但这些是最常见的原因。
答案 2 :(得分:1)
这可能是由于NAT路由器在超时后尝试关闭套接字以释放资源。启用keep_alive可能会有所帮助。您还可以尝试使用静态IP地址创建自己的网络,绕过路由器以排除此假设。
答案 3 :(得分:0)
当连接关闭时,isClosed()
方法应返回TRUE。
即使连接已关闭,isConnected()
方法也可以返回TRUE,因为该方法告诉您“如果您设法连接”,则断开连接时变量状态不会更改/刷新。
但是在您的情况下,根据文档,连接肯定没有关闭。 有关详细信息,请参阅:
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isConnected--
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#isClosed--
注意:可能会帮助您设置为 TRUE setKeepAlive(boolean)
另见:
https://docs.oracle.com/javase/8/docs/api/java/net/SocketOptions.html#SO_KEEPALIVE
https://docs.oracle.com/javase/8/docs/api/java/net/Socket.html#setKeepAlive-boolean-
回到问题,请检查以下其中一项:
如果一切似乎都很好(这是你的Android手机用RST回复)并且SO_KEEPALIVE不起作用那么可能是某些应用程序级错误导致连接中断。