2

我正在尝试轮询服务器端的套接字以检查客户端是否仍然可用。我在这里检查了几个线程,但似乎没有任何效果。

我发现没有直接的检查方法,所以我尝试对套接字执行写操作,并且... Java 正在写入套接字(当客户端断开连接时),并且在预期 IOException 的地方我没有得到任何异常。

我设置了一个线程,它应该每秒执行轮询发送数据包。大约一分钟后发送到断开连接的客户端时,我收到“操作超时”的响应。

我也试图弄乱套接字 setSoTimeout ,但它也没有按预期工作。

有人对如何使它工作有任何建议吗?

非常感谢您提前。

最好的问候,汤姆

4

2 回答 2

1

为什么不进行接收呼叫然后捕获异常。如果你得到一个损坏的管道异常或套接字超时,那么你就知道客户端不再存在。

对于这种情况,典型的方法是让服务器使用 setKeepAlive 和 getKeepAlive 方法设置 TCP keepalive。http://docs.oracle.com/javase/6/docs/api/java/net/Socket.html。如果客户端离开了,那么 TCP keepalive 将启动(因为不活动)并且它会检测到客户端已断开连接。然后,它将关闭连接。任何后续的 recv() 调用都将返回值 -1 和错误指示相同。

于 2013-09-03T18:47:59.110 回答
1

好的,我终于找到了真正有效的解决方案:

InetAddress addr = InetAddress.getByName("192.168.1.121");
addr.isReachable(1000)

像魅力一样工作,反应非常快。事实上,我将它与套接字一起使用,所以在我的情况下,它的工作方式如下:

new Thread() {
  public void run() {
     while(true) {

        try{
            ArrayList<Socket> arr = new ArrayList(clients.values());
                for(int i=0; i<Main.clients.size(); i++){
                    try
                     {
                        InetAddress addr = InetAddress.getByName(arr.get(i).getInetAddress().toString().replace("/", ""));

                        System.out.println(addr.isReachable(1000));


                     }
                     catch (IOException e)
                     {
                    System.out.println("connection probably lost");
                                    e.printStackTrace();
                      }
                 }
          Thread.sleep(1000);
         } catch (Exception e) { System.out.println("Shit happens: "+e); }
      }}
}.start();

它不是真正优化的代码,而且看起来很糟糕,但你得到了它背后的想法。整个代码用于可达主机检测线程。

于 2013-09-04T11:50:35.617 回答