wisdo的博客



千招不来,仓促忽至;十年矜宠,一朝捐弃;人贵知足,唯学不然;人功不竭,天巧不传; 知一重非,进一重境; 亦有生金,一筹而定!

  最近在做项目的时候,遇到这样一个问题,如何判断 Socket 远程端连接是否关闭,如果关闭的话,就要重建连接Socket的类提供了一些已经封装好的方法, 如  isClosed()、isConnected()、isInputStreamShutdown()、isOutputStreamShutdown()等,在测试时发现,这些方法都是本地端的状态,无法判断远端是否已经断开连接。

  其实在socket类中有一个方法sendUrgentData,它会往输出流发送一个字节的数据,只要对方Socket的SO_OOBINLINE属性没有打开,就会自动舍弃这个字节(在Java 中是抛出异常),而SO_OOBINLINE属性默认情况下就是关闭的。

  以下是示例代码仅供参考:

public class Nksocket extends Thread{  
public String ip=null;//连接服务器的IP  
public Integer port=null;//连接服务器的端口  
private Socket socket=null;//套节字对象  
private boolean close = false; // 关闭连接标志位,true表示关闭,false表示连接  
private Integer sotimeout=1*1*10;//超时时间,以毫秒为单位  
//------------------------------------------------------------------------------  
public Nksocket(){  
   init();  
}  
public Nksocket(String ip,Integer port){  
   setIp(ip);  
   setPort(port);  
   init();  
}  
/** 
* 初始化socket对象 
*/  
public void init(){  
   try {  
    InetAddress address = InetAddress.getByName(getIp());  
    socket = new Socket(address,getPort());  
    socket.setKeepAlive(true);//开启保持活动状态的套接字  
    socket.setSoTimeout(sotimeout);//设置超时时间  
    close=!Send(socket,"2");//发送初始数据,发送成功则表示已经连接上,发送失败表示已经断开  
   }catch(UnknownHostException e) {  
    e.printStackTrace();  
   }catch(IOException e){  
    e.printStackTrace();  
   }  
}  
/** 
* 读数据线程 
*/  
public void run() {  
   while(true){  
    //---------读数据---------------------------  
    close = isServerClose(socket);//判断是否断开  
    if(!close){//没有断开,开始读数据  
     String readtext = ReadText(socket);  
     if(readtext!=null && readtext.trim().length()>0){  
      System.out.println("读取数据:"+readtext);  
     }  
    }  
    //---------创建连接-------------------------  
    while(close){//已经断开,重新建立连接  
     try{  
      System.out.println("重新建立连接:"+getIp()+":"+getPort());  
      InetAddress address = InetAddress.getByName(getIp());  
      socket = new Socket(address,getPort());  
      socket.setKeepAlive(true);  
      socket.setSoTimeout(sotimeout);  
      close = !Send(socket,"2");  
      System.out.println("建立连接成功:"+getIp()+":"+getPort());  
     }catch(Exception se){  
      System.out.println("创建连接失败:"+getIp()+":"+getPort());  
      close=true;  
     }  
    }  
   }  
}  
/** 
* 发送数据,发送失败返回false,发送成功返回true 
* @param csocket 
* @param message 
* @return 
*/  
public Boolean Send(Socket csocket,String message){  
   try{  
    PrintWriter out = new PrintWriter(socket.getOutputStream(), true);  
    out.println(message);  
    return true;  
   }catch(Exception se){  
    se.printStackTrace();  
    return false;  
   }  
}  
/** 
* 读取数据,返回字符串类型 
* @param csocket 
* @return 
*/  
public String ReadText(Socket csocket){  
   try{  
    csocket.setSoTimeout(sotimeout);  
    InputStream input = csocket.getInputStream();  
    BufferedReader in = new BufferedReader(new InputStreamReader(input));  
    char[] sn = new char[1000];  
    in.read(sn);  
    String sc = new String(sn);  
    return sc;  
   }catch(IOException se){  
    return null;  
   }  
}  
/** 
* 判断是否断开连接,断开返回true,没有返回false 
* @param socket 
* @return 
*/  
public Boolean isServerClose(Socket socket){  
   try{  
    socket.sendUrgentData(0xFF);//发送1个字节的紧急数据,默认情况下,服务器端没有开启紧急数据处理,不影响正常通信  
    return false;  
   }catch(Exception se){  
    return true;  
   }  
}  
/** 
* 测试 
* @param ags 
*/  
public static void main(String[] ags){  
   Nksocket nksocket = new Nksocket("127.0.0.1",8090);  
   nksocket.start();  
}  
//------------------------------------------------------------------------------  
public String getIp() {  
   return ip;  
}  
public void setIp(String ip) {  
   this.ip = ip;  
}  
public Integer getPort() {  
   return port;  
}  
public void setPort(Integer port) {  
   this.port = port;  
}  
}  

  

参考资料:

 http://blog.csdn.net/xyz_lmn/article/details/6146749

http://ivan4126.blog.163.com/blog/static/20949109220135284278806/

posted on 2016-09-10 17:35  wisdo  阅读(34807)  评论(3编辑  收藏  举报