问题描述: 
    建立一个TCP SOCKET,服务器端跑的是C程序,客户端是通过页面执行的JAVA APPLET程序。当服务器端断电,关闭了SOCKET,客户端的程序,偶调用socket.iscloesd(),值为false,调用socket.isconnect(),值为true,为什么socket还有连接呢?还没有关闭呢?但是服务端已经关闭了,很奇怪! 
    请各位大虾指点一二!     多谢,高分奉送

解决方案 »

  1.   

    可能需要一定的间隔吧TCP是有连接的,服务器断电,没有向客户端通知状态
    关注ing
      

  2.   

    在断电之前,socket.iscloesd(),值为false,调用socket.isconnect(),值为true,这些都是正确的.楼主的疑问是服务器断电之后,然后调用客户端的isclosed()    isconnect(),这时,显然除了只是服务器断电了,并没有任何的动作作用到客户端,当调用函数测试客户端的状态,客户端并不是再向服务器发送消息以确定连接状态,而是直接调用断电之前客户端处的状态信息.所以调用得到的信息和断电之前还是一样的.只是这里已经不能再发送任何信息了.
      

  3.   

    答:socket.iscloesd()是检测你的socket有没有调用close()关闭过.若没有调用,则它返回的是false.则:socket.isconnect()是当你的TCP三步握手成功之后,就开始处于connected状态.当你调用close()之后,即使socket.iscloesd()已经是true,调用socket.isconnect(),仍然可能为true(这是因为你的socket可能还处于TCP的TIME-WAITTNG状态,这也是为什么有这个setReuseAddress(..)了 )
    而:楼主的问题是:服务器端突然断电,因而服务器端程序来不及进入TCP的四步释放TCP连接的步骤,没有向TCP客户机发TCP报文进通知,因而TCP客户机方一无所知,TCP客户机方的TCP仍然保持原来的状态不变.过一段时间后,由于TCP的保活定时器的作用,TCP客户机方才会终于知道,服务器方已不在线了.
    通常写程序时,都一依赖于TCP的保活定时器,而是程序员自己定义保活的"协议"--如:每隔10分钟,发一个保活通知等等..
      

  4.   

    多谢楼上各位给出的分析
    那偶现在要怎样才能知道服务器断电之后SOCKET断开连接的情况呢?
    偶现在只是想处理当服务器断电之后,客户端怎样才能知道,并且做出相应的处理,提醒用户SERVER端已经断开连接
    多谢!
      

  5.   


    是不是一般不依赖于TCP的保活定时器啊?
    那自己怎么设置它的保活机制呢?
      

  6.   

    那偶现在要怎样才能知道服务器断电之后SOCKET断开连接的情况呢? 
    偶现在只是想处理当服务器断电之后,客户端怎样才能知道,并且做出相应的处理,提醒用户SERVER端已经断开连接 
    多谢!是不是一般不依赖于TCP的保活定时器啊? 
    那自己怎么设置它的保活机制呢?答:1)一般不依赖于TCP的保活定时器,要自己定义一个"保活机制".2)现在只是想处理当服务器断电之后,客户端怎样才能知道,并且做出相应的处理?
    恰恰相反,这个问题更多的是:服务器方要知道,客户端断电之后,服务器怎样才能知道,并且释放客户机在服务器上登录后所占用的资源.(即:服务器方更需要对客户机方是否在线进行判断,以便释放相关的占用服务器的资源).3)你的情况,方法很多.简单的做法可以是:只要在从socket上从服务器上读取数据时,设定超时选项,超时一到,就认为服务器不在线了(并不一定是真的不正线,如:服务器太忙了,没有响应).这是因为:向服务器写时,若服务器不在线,会有I/O异常出现的,你会获取到的. 这样无论是读,还是写,都可判断出了.
      

  7.   

    感谢楼上的答复
    偶现在在从SERVER端读取数据时,已经设置了超时,并且能够捕获到异常
    但是问题是如果SERVER端断电之后,偶再向SERVER端发送消息时,要怎样捕获这个异常处理呢?
    我用的是PrintSream这个对象,好像它本身没有I/O异常处理,请指教!主要是捕获SOCKET不能正常通信这个异常。
      

  8.   

    答:用PrintSream流的checkError()来检查低层SOCKET的OutputStream流的IOException.若有异常,则表明网络通信出错了.
      

  9.   

     
    答:用PrintSream流的checkError()来检查低层SOCKET的OutputStream流的IOException.若有异常…
    [/Quote]偶按照你的说法,结果还是显示,当服务器端断电之后,没有任何异常出现,checkError()的值都是false,表示没有错误
    贴出代码,
      private OutputStream fOut1;
      private PrintStream out1;
      private Socket sock1;
      ...
      try{
      sock1=new Socket("192.168.0.224",6668);
      }catch(SocketException e){
       e.printStackTrace();
      }
      ...
      测试的的是下面的代码
         try {
           fOut1 = sock1.getOutputStream();
           out1 = new PrintStream(fOut);
         }catch(IOException e1){
           e1.printStackTrace();
         }
           System.out.println(out1.checkError());   运行结果是,正常连接的情况下是没有错误和任何异常,服务器断电之后还是没有任何异常。
       用的是同一个SOCKET,这个SOCKET在服务器断电前后是同一个,没有新建。
       请楼上麻烦看一下!多谢
      

  10.   

    答:你要向服务器写数据啊.然后再用checkError()检测写操作是否发生了IO异常啊.
    当服务器断电时:
    1)你进行读数据操作.则可借助"读操作超时"来判断服务器是否可能不在线了
    2)你进行写数据操作,则可借助 PrintStream 的checkError()来检测是否发生了IO异常
    3)你不读,又不写只是静静地等待,则此时只有间隔了一个较长的时间后,TCP的保活定时器发生作用,你的程序才会得到网络产生异常.
      

  11.   


    你说的写数据操作,请问是在写之前还是写之后用checkError(),偶在写之前检测是没有错误的,要在写之后吗?
    偶多说的写就是
      private OutputStream fOut1; 
      private PrintStream out1; 
      private Socket sock1; 
      ... 
      try{ 
      sock1=new Socket("192.168.0.224",6668); 
      }catch(SocketException e){ 
      e.printStackTrace(); 
      } 
      ... 
      测试的的是下面的代码 
        try { 
          fOut1 = sock1.getOutputStream(); 
          out1 = new PrintStream(fOut); 
        }catch(IOException e1){ 
          e1.printStackTrace(); 
        } 
          System.out.println(out1.checkError()); 
         String com="111111eeee";
         ou1.println(com);
       就是上面这个标注为红色的语句
       在之前还是之后呢?
       之前没有效果
       多谢!
      

  12.   

    就是上面这个标注为红色的语句 
      在之前还是之后呢? 
      之前没有效果 
      多谢!
    答:
    1)写操作必须放在前面.
    2)先写,后用checkError()来检测
    3)若对方机器在线,但已正常关闭了SOCKET,则checkError()能几乎立即检测到错误
    4)若对方机器突然掉电,则你写操作后,低层TCP协议会将你的数据发给已掉电的服务器,当TCP报文超时时,低层TCP协议会重试多次,当超过一定次数时,你的checkError()才会检测到错误(即:错误不是马上就能检测到的,会有一个迟后,这是TCP低层重试多次的时间),因此:大部分情况下,不你做了几次写操作后,才会检测到前面的某一次写操作其实是失败的(即:checkError()的检测对于第4)情况是迟后的.)
      

  13.   

    的确如楼上所说,当服务器断电之后,不是马上就检测到出错。
    偶已经试过了,在断电之后,调用checkError()是false,证明当时是没有错误的。
    换句话说,也就是当服务器断电之后,我用checkError(),即时是检测不到SOCKET已经不存在,不能进行正常的读写了?
    如果服务器端突然断电,我向输出流写数据的时候,怎样才能当时就知道不能正常通信了呢?只能用超时机制吗?
    请LS指教!
    多谢!