使用TCP KeepAlive检测套接字断开

时间:2013-11-05 10:09:57

标签: java multithreading sockets tcp ip

我正在开发一个通过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();
        }
    }
}

非常感谢任何反馈。

5 个答案:

答案 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而不是自己处理连接问题。这可以改善,例如电池消耗。