我正在开发一个通过TCP / IP托管第三方设备的服务器,并且一直遇到突然的连接丢失(设备通过蜂窝连接)。我需要找到一种检测断开连接的方法,而不必将数据写入设备本身。
我已经看过使用TCP keepalive功能,但Java似乎不允许任何调整keepalive操作的时间。
有没有建议的方法呢?
我的简化套接字代码如下:
public class Test2Socket {
public static void main(String[] args) {
try {
ServerSocket skt = new ServerSocket(1111);
Socket clientSocket = skt.accept();
clientSocket.setKeepAlive(true);
System.out.println("Connected..");
BufferedReader input = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String inputLine;
while((inputLine = input.readLine()) != null)
{
System.out.println(inputLine);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
非常感谢任何反馈。
答案 0 :(得分:8)
您将无法完成TCP堆栈的内置保持活动。这是因为应用程序无法调整保持活动间隔,它由操作系统设置,默认值相当高(小时)。这不是Java特有的。
如果你需要在合理的时间内超时,你必须在要使用的协议中实现某种保持活力。我见过的大多数高级协议都有某种NOP功能,你发送“你在吗?”消息,另一方发送“是的,我在这里”回复,没有做任何其他事情。
答案 1 :(得分:3)
有关TCP Keep-Alives的深入讨论,请参阅我的回答here。
但基本上TCP Keep-Alives可能是检测陈旧连接的最佳方法。主要问题是操作系统默认设置是在检查连接之前的2小时设置了11分钟的Keep-Alive数据包,然后才真正删除连接。
当TCP内置协议时,不要编写自己的应用程序层Keep Alive协议。所有你需要做的就是set the TCP time out更合理的事情,比如2-3分钟。
不幸的是,由于TCP超时是在操作系统级而不是在JVM内管理的,因此很难(但并非不可能)在每个插槽的代码中配置TCP超时。
答案 2 :(得分:0)
设置读取超时,将setSoTimeout(),
设置为合理的值,比如预期的响应时间加倍,并捕获生成的SocketTimeoutException.
注意,没有“Java TCP KeepAlive”这样的东西。
答案 3 :(得分:0)
在套接字上调用setKeepalive()时,将使用系统参数(可调)。 (使用openjdk7在Debian 8下检查它。)
因为我需要完全相同的功能,所以我写了一个名为libdontdie的小型库,它可以预加载并与Java一起使用。
答案 4 :(得分:0)
this图书馆的作者 这里: - )
如前所述,除非您依赖于直接在TCP协议中实现的难以配置的功能(保持活动),否则在没有实际通过连接发送数据的情况下很难检测到故障。
引用的库封装了传统的Java套接字,同时添加了易于配置的定期连接检查和确认。 (那些将对应用程序员保持不可见)。 一旦发现故障,将通知所有登记的观察员。 (取决于您可以接近实时的配置。)
好处是lib很容易使用(至少在我自己的项目中工作非常可靠)。
缺点是,应用程序层不应用于连接检查。所以基本上,lib正在以他们可能不想要的方式使用东西。
旁注: 你提到你的客户是cellulars。虽然链接库将在Android上运行,但您可能需要查看Push Notification Services而不是自己处理连接问题。这可以改善,例如电池消耗。