Java Socket基础

         较基础的Java Socket通信样例!
 
一、长连接通信
         客户端和服务端建立通道后,Socket一直开着。两端通过read()等待消息。
 
1 )简易聊天
         服务端可主动对各个客户端发送消息,而各客户端只能单独发送给服务端。当然,只要你愿意,在服务端改下,即可转发了。
         附件解压工程ChatSocket,运行TestServer、TestClient即可。src下还有两批处理,详细看TestServer文件内注释了。
 
1.1)ChatServer.java
 
  
  1. /** 
  2.  * 长连接、1对n主动发消息的服务器 
  3.  *  
  4.  * @author Join 
  5.  */ 
  6. public class ChatServer extends Thread { 
  7.  
  8.     /** 服务端口 */ 
  9.     private int port; 
  10.     /** 服务套接字 */ 
  11.     private ServerSocket mServerSocket; 
  12.     /** 线程池 */ 
  13.     private ExecutorService pool; 
  14.     /** 客户端套接字集合 */ 
  15.     private ArrayList<Socket> mClientList; 
  16.  
  17.     public ChatServer(int port) { 
  18.         this.port = port; 
  19.         pool = Executors.newCachedThreadPool(); // 缓存线程池 
  20.         mClientList = new ArrayList<Socket>(); 
  21.     } 
  22.  
  23.     @Override 
  24.     public void run() { 
  25.         try { 
  26.             mServerSocket = new ServerSocket(port); // 创建本地特定端口服务器套接字 
  27.             Socket client = null
  28.             while (true) { 
  29.                 client = mServerSocket.accept(); // 接收连接的套接字 
  30.                 mClientList.add(client); // 加入客户端列表 
  31.                 System.out.println(client.getInetAddress() + "建立了连接"); 
  32.                 pool.execute(new ThreadServer(client)); // 新线程执行任务 
  33.             } 
  34.         } catch (BindException e) { // 端口使用中 
  35.             System.out.println("端口使用中,请关闭后重开!"); 
  36.         } catch (IOException e) { 
  37.             e.printStackTrace(); 
  38.         } 
  39.     } 
  40.  
  41.     /** 各个连接客户端的服务线程 */ 
  42.     private class ThreadServer extends Thread { 
  43.  
  44.         private Socket client; 
  45.  
  46.         public ThreadServer(Socket client) { 
  47.             this.client = client; 
  48.         } 
  49.  
  50.         @Override 
  51.         public void run() { 
  52.             DataInputStream in = null
  53.             DataOutputStream out = null
  54.             try { 
  55.                 in = new DataInputStream(client.getInputStream()); 
  56.                 out = new DataOutputStream(client.getOutputStream()); 
  57.                 BufferedReader wt = new BufferedReader(new InputStreamReader( 
  58.                         System.in)); // 控制台输入流 
  59.                 while (true) { 
  60.                     if (in.available() > 0) { 
  61.                         /* 有数据时接收 */ 
  62.                         String str = in.readUTF(); 
  63.                         System.out.println(str); 
  64.                         /* 接收end或空时,退出 */ 
  65.                         if (null == str || "end".equals(str)) { 
  66.                             System.out 
  67.                                     .println(client.getInetAddress() + "正常退出"); 
  68.                             break
  69.                         } 
  70.                         /* 回复或转发已接收数据 */ 
  71.                     } else { 
  72.                         if (wt.ready()) { 
  73.                             /* 控制台有数据时发送 */ 
  74.                             String str = wt.readLine(); 
  75.                             sendMessage(str); // 群发消息 
  76.                         } else { 
  77.                             try { 
  78.                                 /* 发送紧急数据,判断连接 */ 
  79.                                 client.sendUrgentData(0xFF); 
  80.                                 Thread.sleep(100); 
  81.                             } catch (Exception e) { 
  82.                                 System.out.println(client.getInetAddress() 
  83.                                         + "断开连接"); 
  84.                                 break
  85.                             } 
  86.                         } 
  87.                     } 
  88.                 } 
  89.             } catch (SocketException e) { // Connection reset 
  90.                 System.out.println(client.getInetAddress() + "异常退出"); 
  91.             } catch (IOException e) { 
  92.                 e.printStackTrace(); 
  93.             } finally { 
  94.                 mClientList.remove(client); // 移除当前客户端 
  95.                 try { 
  96.                     if (null != in) { 
  97.                         in.close(); 
  98.                     } 
  99.                     if (null != out) { 
  100.                         out.close(); 
  101.                     } 
  102.                     if (null != client) { 
  103.                         client.close(); 
  104.                     } 
  105.                 } catch (IOException e) { 
  106.                     e.printStackTrace(); 
  107.                 } 
  108.             } 
  109.         } 
  110.  
  111.     } 
  112.  
  113.     /**  
  114.      * 群发信息  
  115.      * @throws IOException 
  116.      */ 
  117.     public void sendMessage(String msg) throws IOException { 
  118.         DataOutputStream out = null
  119.         for (Socket client : mClientList) { 
  120.             out = new DataOutputStream(client.getOutputStream()); 
  121.             out.writeUTF(msg); 
  122.             out.flush(); 
  123.         } 
  124.     } 
  125.  
 
1.2)ChatClient.java
 
  
  1. /** 
  2.  * 接收和发送消息的客户端 
  3.  *  
  4.  * @author Join 
  5.  */ 
  6. public class ChatClient extends Thread { 
  7.  
  8.     /** 套接字地址 */ 
  9.     private SocketAddress address; 
  10.     /** 超时时间 */ 
  11.     private int timeout; 
  12.  
  13.     public ChatClient(String host, int port, int timeout) { 
  14.         this.address = new InetSocketAddress(host, port); 
  15.         this.timeout = timeout; 
  16.     } 
  17.  
  18.     @Override 
  19.     public void run() { 
  20.         Socket socket = new Socket(); // 创建未连接套接字 
  21.         try { 
  22.             // socket.setOOBInline(false); // 默认即是false,表示不处理紧急数据 
  23.             socket.connect(address, timeout); // 连接到服务器,并指定超时时间 
  24.             handleSocket(socket); // 数据接收发送处理 
  25.         } catch (ConnectException e) { // 拒绝连接 
  26.             System.out.println("连接不上服务器"); 
  27.         } catch (SocketTimeoutException e) { // 连接超时 
  28.             System.out.println("连接服务器超时"); 
  29.         } catch (IOException e) { 
  30.             e.printStackTrace(); 
  31.         } finally { 
  32.             try { 
  33.                 if (null != socket) { 
  34.                     socket.close(); // 关闭Socket 
  35.                 } 
  36.             } catch (IOException e) { 
  37.                 e.printStackTrace(); 
  38.             } 
  39.         } 
  40.     } 
  41.  
  42.     private void handleSocket(Socket socket) { 
  43.  
  44.         DataInputStream in = null
  45.         DataOutputStream out = null
  46.         try { 
  47.             in = new DataInputStream(socket.getInputStream()); 
  48.             out = new DataOutputStream(socket.getOutputStream()); 
  49.             BufferedReader wt = new BufferedReader(new InputStreamReader( 
  50.                     System.in)); // 控制台输入流 
  51.             while (true) { 
  52.                 if (wt.ready()) { 
  53.                     /* 控制台有数据时发送 */ 
  54.                     String str = wt.readLine(); 
  55.                     out.writeUTF(str); 
  56.                     out.flush(); 
  57.                     /* 发送end时,自身也退出 */ 
  58.                     if (str.equals("end")) { 
  59.                         break
  60.                     } 
  61.                 } else { 
  62.                     try { 
  63.                         /* 发送紧急数据,判断连接 */ 
  64.                         socket.sendUrgentData(0xFF); 
  65.                         Thread.sleep(100); 
  66.                     } catch (Exception e) { 
  67.                         System.out.println("服务器断开连接"); 
  68.                         break
  69.                     } 
  70.                 } 
  71.                 /* 有数据时接收并输出 */ 
  72.                 if (in.available() > 0
  73.                     System.out.println(in.readUTF()); 
  74.             } 
  75.         } catch (SocketException e) { // Connection reset 
  76.             System.out.println("服务器异常"); 
  77.         } catch (IOException e) { 
  78.             e.printStackTrace(); 
  79.         } finally { 
  80.             try { 
  81.                 if (null != in) { 
  82.                     in.close(); 
  83.                 } 
  84.                 if (null != out) { 
  85.                     out.close(); 
  86.                 } 
  87.             } catch (IOException e) { 
  88.                 e.printStackTrace(); 
  89.             } 
  90.         } 
  91.     } 
  92.  

Java Socket基础(二)