最近看到这么一段话
出处:http://blog.csdn.net/ /archive/2009/01/05/3714667.aspx
第2个问题是对长连接的维护。所谓的维护包括两个方面,首先是检测对方的主动断
连(既调用Socket的close方法),其次是检测对方的宕机、异常退出及网络不
通。这是一个健壮的通信程序必须具备的。检测对方的主动断连很简单,主要
一方主动断连,另一方如果在进行读操作,则此时的返回值只-1,一旦检测到
对方断连,则应该主动关闭己方的连接(调用Socket的close方法)。而检测对
方的宕机、异常退出及网络不通常用方法是用“心跳”,也就是双方周期性的发送数
据给对方,同时也从对方接收“心跳”,如果连续几个周期都没有收到对方心跳,则
可以判断对方或者宕机或者异常推出或者网络不通,此时也需要主动关闭己方连接,如果
是客户端可在延迟一定时间后重新发起连接。虽然Socket有一个keep alive选项来维护连
接,如果用该选项,一般需要两个小时才能发现对方的宕机、异常退出及网络不通。 不知道这段话是否正确,socketchannel.read 方法里面的说明是,如果返回 -1 ,表示读取到了流的末尾,但是我认为不一定是对方关闭了连接...

解决方案 »

  1.   

    如果是对方主动关闭了连接,你在读数据的时候会有“Connection closed by peer”这个异常出来的
    正常情况下如果阻塞模式,没有断开应该是读阻塞,不会有返回的,执行read()方法的这个线程一直挂着
    用nio非阻塞模式,没数据的话遍历selector的时候是不会遍历到的
      

  2.   

    就是用 nio 非阻塞通信,发现回进入死循环一样的。如果对方关闭了连接,确实发现读数据返回了 -1,应该可以确认是对方关闭连接,包括异常关闭,也会检测到(windows)
      

  3.   

    在nio非阻塞模式中,如果客户端主动断开连接时,FD_READ仍然是有效的,所以Selector可以遍历到,这时候读数据返回的确实是-1,可以用这个来判断是否关闭连接
      

  4.   

    可以尝试在该连接中写入一个字节的数据,如果写失败,可以判断该连接已断开。
    如果读的话,非nio会一直阻塞,超时时间不好确定。
      

  5.   

    使用sendUrgentData()函数,使用方法可以参考JAVA API手册,如下:
    sendUrgentData
    public void sendUrgentData(int data)
                        throws IOException在套接字上发送一个紧急数据字节。要发送的字节是数据参数的八个最低位。紧急字节在对套接字 OutputStream 的所有预先写入之后但在任何以后写入之前发送。 参数:
    data - 要发送的数据字节 
    抛出: 
    IOException - 如果发送数据时发生错误。
    从以下版本开始: 
    1.4 
    如:下面的片段可用于服务端和客户端 ,来判断对方是否仍连接
    public void run()
    {try
    {
    while(1)
    {
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    }
    client.sendUrgentData(0x0);
    }
    } catch (IOException e) {
    System.out.println("与服务器失去连接!!!!");
    }}
      

  6.   


    sendUrgentData这个方法有些莫名吧,如果连接没有断开,还有效的情况下,你发一个这样的数据,回不会把协议栈搞乱了??
      

  7.   

    我的想法是这样检测对方的连接是否已经关闭:
    1.在对方的关闭方法中加一参数作为标记,一般是Boolean类型参数.
    2.在自己这方需要连接对方的方法之前加个判断,如果对方已经关闭,则连接不上,否则连接上.
    这方法只是简单的检测是否关闭.