java之socket的OOBInline和UrgentData和发送心跳包研究

来源:互联网 发布:pp助手 mac 备份app 编辑:程序博客网 时间:2024/05/20 09:08

UrgentData可以理解为紧急发送数据方式,如果我们客户端先用write方法写入数据,再用UrgentData发送数据,再去执行flush操作,我们可以得到服务端先打印UrgentData发送的数据,然后再打印write写入的数据。

客户端代码实现:

[html] view plain copy
 print?
  1. package com.chenyu.string.cn;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.OutputStream;  
  5. import java.io.OutputStreamWriter;  
  6. import java.net.Socket;  
  7.   
  8. public class ClientTest {  
  9.       
  10.     public static Socket socket;  
  11.     public static final String LocalHOST = "127.0.0.1";  
  12.     public static final int PORT = 1234;  
  13.       
  14.     public static void main(String[] args) {  
  15.         Client(LocalHOST, PORT);  
  16.     }  
  17.       
  18.     public static void Client(String address, int port) {  
  19.         try {  
  20.             socket = new Socket(address, port);  
  21.         } catch (Exception e) {  
  22.             System.out.println("connection reset");  
  23.             return;  
  24.         }  
  25.         if (socket != null && socket.isConnected()) {  
  26.             try {  
  27.                 socket.setOOBInline(true);  
  28.                 OutputStream out = socket.getOutputStream();  
  29.                 OutputStreamWriter outWriter = new OutputStreamWriter(out);  
  30.                 outWriter.write(67); // 向服务器发送字符"C"  
  31.                 outWriter.write("hello world\r\n");  
  32.                 socket.sendUrgentData(65); // 向服务器发送字符"A"  
  33.                 socket.sendUrgentData(322); // 向服务器发送字符"B"  
  34.                 outWriter.flush();  
  35.                 socket.sendUrgentData(214); // 向服务器发送汉字”中”  
  36.                 socket.sendUrgentData(208);  
  37.                 socket.sendUrgentData(185); // 向服务器发送汉字”国”  
  38.                 socket.sendUrgentData(250);  
  39.                 socket.close();  
  40.             } catch (Exception e) {  
  41.                 System.out.println("has throw exception");  
  42.                 e.printStackTrace();  
  43.             } finally {  
  44.                 try {  
  45.                     if (socket != null) {  
  46.                         socket.close();  
  47.                     }  
  48.                 } catch (IOException e) {  
  49.                     System.out.println("socket close fail");  
  50.                 }  
  51.             }  
  52.         } else {  
  53.             System.out.println("socket is null or socket connect fail");  
  54.         }  
  55.     }  
  56. }  

服务端代码实现:

[html] view plain copy
 print?
  1. package com.chenyu.string.cn;  
  2.   
  3. import java.io.BufferedReader;  
  4. import java.io.IOException;  
  5. import java.io.InputStream;  
  6. import java.io.InputStreamReader;  
  7. import java.net.ServerSocket;  
  8. import java.net.Socket;  
  9.   
  10. public class TestInline {  
  11.       
  12.     public static ServerSocket serverSocket;  
  13.     public static Socket socket;  
  14.     public static void main(String[] args) {  
  15.           
  16.         try {  
  17.             serverSocket = new ServerSocket(1234);  
  18.         } catch (IOException e1) {  
  19.             System.out.println("serverSocket is fail");  
  20.             return;  
  21.         }  
  22.           
  23.         System.out.println("服务器已经启动,端口号:1234");  
  24.           
  25.         while (true) {  
  26.             try {  
  27.             <span style="white-space:pre">  </span>socket = serverSocket.accept();  
  28.                 socket.setOOBInline(true);  
  29.                 InputStream in = socket.getInputStream();  
  30.                 InputStreamReader inReader = new InputStreamReader(in);  
  31.                 BufferedReader bReader = new BufferedReader(inReader);  
  32.                 String result;  
  33.                 while ((result = bReader.readLine()) != null) {  
  34.                     System.out.println(result);  
  35.                 }  
  36. //              char [] cha = new char[1024];  
  37. //              int len = inReader.read(cha);  
  38. //              System.out.println(new String(cha,0,len));  
  39.                 socket.close();  
  40.             } catch (Exception e){  
  41.                 System.out.println("read data fail");  
  42.             } finally {  
  43.                 if (socket != null) {  
  44.                     try {  
  45.                         socket.close();  
  46.                     } catch (IOException e) {  
  47.                         System.out.println("socket close fail");  
  48.                     }  
  49.                 }  
  50.             }  
  51.         }  
  52.     }  
  53. }  

运行结果(先运行服务端,后运行客户端):

[html] view plain copy
 print?
  1. 服务器已经启动,端口号:1234  
  2. ABChello world  
  3. 中国  

说明使用sendUrgentData方法发送数据后,系统会立即将这些数据发送出去;而使用write发送数据,必须要使用flush方法才会真正发送数据。
在使用setOOBInline方法打开SO_OOBINLINE选项时要注意是必须在客户端和服务端程序同时使用setOOBInline方法打开这个选项,否则无法命名用sendUrgentData来发送数据。


总结:

我们还可以通过socket.sendUrgentData(0xff);来检测是否与服务端连通,和ping IP 效果差不多,其它的socket.isConnected() socket.isOutputShutdown()都是本地检测,我们上面socket发送数据,如果在安卓客户端,我们可以用这个来发送心跳包,
类似上面客户端的代码,通过后台下发的IP和端口配置,开启线程,out.write(data),通过handler.postDelay(Runable, delayTime)发送心跳包给服务端。