Java Socket基础(一)


2 )对象消息
         发送对象消息。服务端有LinkServer和LinkServer2两个,分别支持单客户端与多客户端,方式也有些不一样。
         附件解压工程LinkedSocketB,.test包内Test开头的即是测试类了。服务端接收到客户端连接时,直接一个循环发送n个对象过去,没什么大问题^^。
 
2.1)LinkClient.java
 
    
  1. /** 
  2.  * 只建立一个Socket,长连接Server接收数据。 
  3.  * 
  4.  * @author Join 
  5.  */ 
  6. public class LinkClient extends Thread { 
  7.   
  8.     /** 套接字地址 */ 
  9.     private SocketAddress address; 
  10.     /** 超时时间 */ 
  11.     private int timeout; 
  12.     /** 客户端监听接口 */ 
  13.     private OnLinkClientListener listener; 
  14.   
  15.     /** 
  16.      * 构造客户端 
  17.      * 
  18.      * @param host 服务器名称 
  19.      * @param port 服务器端口 
  20.      * @param timeout 连接超时时间 
  21.      */ 
  22.     public LinkClient(String host, int port, int timeout) { 
  23.        this.address = new InetSocketAddress(host, port); 
  24.        this.timeout = timeout; 
  25.     } 
  26.   
  27.     @Override 
  28.     public void run() { 
  29.        Socket socket = new Socket(); // 创建未连接套接字 
  30.        try { 
  31.            socket.connect(address, timeout); // 连接到服务器,并指定超时时间 
  32.            if (null != listener) { 
  33.               listener.onConnected(); 
  34.            } 
  35.            receiveObj(socket); // 接收服务器数据 
  36.        } catch (ConnectException e) { // 拒绝连接 
  37.            if (null != listener) { 
  38.               listener.onConnectException(); 
  39.            } 
  40.        } catch (SocketTimeoutException e) { // 连接超时 
  41.            if (null != listener) { 
  42.               listener.onTimeoutException(); 
  43.            } 
  44.        } catch (IOException e) { 
  45.            e.printStackTrace(); 
  46.        } finally { 
  47.            try { 
  48.               if (null != socket) { 
  49.                   socket.close(); // 关闭Socket 
  50.               } 
  51.            } catch (IOException e) { 
  52.               e.printStackTrace(); 
  53.            } 
  54.        } 
  55.     } 
  56.   
  57.     /** 接收服务器发送的对象 */ 
  58.     private void receiveObj(Socket socket) { 
  59.        // socket.shutdownOutput(); // 半关闭输出流 
  60.  
  61.        ObjectInputStream is = null
  62.        try { 
  63.            is = new ObjectInputStream(new BufferedInputStream( 
  64.                   socket.getInputStream())); 
  65.            /** 循环接收对象 */ 
  66.            while (true) { 
  67.               Object obj = is.readObject(); 
  68.               if (null == obj) { 
  69.                   break
  70.               } 
  71.               if (null != listener) { 
  72.                   listener.onReceive(obj); 
  73.               } 
  74.            } 
  75.            if (null != listener) { 
  76.               listener.onExited(); 
  77.            } 
  78.        } catch (SocketException e) { // Connection reset 
  79.            if (null != listener) { 
  80.               listener.onSocketException(); 
  81.            } 
  82.        } catch (IOException e) { 
  83.            e.printStackTrace(); 
  84.        } catch (ClassNotFoundException e) { 
  85.            e.printStackTrace(); 
  86.        } finally { 
  87.            try { 
  88.               if (null != is) { 
  89.                   is.close(); 
  90.               } 
  91.               if (null != socket) { 
  92.                   socket.close(); 
  93.               } 
  94.            } catch (IOException e) { 
  95.               e.printStackTrace(); 
  96.            } 
  97.        } 
  98.     } 
  99.   
  100.     /** 设置客户端监听接口 */ 
  101.     public void setOnLinkClientListener(OnLinkClientListener listener) { 
  102.        this.listener = listener; 
  103.     } 
  104.   
 
2.2)LinkServer.java
 
    
  1. /** 
  2.  * 开启服务器,长连接一个Socket,主动发送数据 
  3.  * 
  4.  * @author Join 
  5.  */ 
  6. public class LinkServer extends Thread { 
  7.   
  8.     /** 服务端口 */ 
  9.     private int port; 
  10.     /** 服务套接字 */ 
  11.     private ServerSocket mServerSocket; 
  12.     /** 线程池 */ 
  13.     private ExecutorService pool; 
  14.     /** 服务器监听接口 */ 
  15.     private OnLinkServerListener listener; 
  16.   
  17.     /** 同步对象 */ 
  18.     private Object lockObj = new Object(); 
  19.     /** 是否等待 */ 
  20.     private boolean isWaiting = false
  21.     /** 发送对象集合 */ 
  22.     private ArrayList<Object> sendObjList; 
  23.   
  24.     public LinkServer(int port) { 
  25.        this.port = port; 
  26.        pool = Executors.newCachedThreadPool(); // 缓存线程池 
  27.        sendObjList = new ArrayList<Object>(); 
  28.     } 
  29.   
  30.     @Override 
  31.     public void run() { 
  32.        try { 
  33.            mServerSocket = new ServerSocket(port); // 创建本地特定端口服务器套接字 
  34.            Socket client = null
  35.            client = mServerSocket.accept(); // 接收连接的套接字 
  36.            if (null != listener) { 
  37.               listener.onClientConnected(client.getInetAddress()); 
  38.            } 
  39.            pool.execute(new ThreadServer(client)); // 新线程执行任务 
  40.         } catch (BindException e) { // 端口使用中 
  41.  
  42.            if (null != listener) { 
  43.               listener.onBindException(); 
  44.            } 
  45.        } catch (IOException e) { 
  46.            e.printStackTrace(); 
  47.        } 
  48.   
  49.     } 
  50.   
  51.     /** 各个连接客户端的服务线程 */ 
  52.     private class ThreadServer extends Thread { 
  53.   
  54.        private Socket client; 
  55.   
  56.        public ThreadServer(Socket client) { 
  57.            this.client = client; 
  58.        } 
  59.   
  60.        @Override 
  61.        public void run() { 
  62.            ObjectOutputStream os = null
  63.            try { 
  64.               os = new ObjectOutputStream(client.getOutputStream()); 
  65.   
  66.               Object sendObj; 
  67.               synchronized (lockObj) { 
  68.                   while (true) { 
  69.                      if (sendObjList.size() <= 0) { 
  70.                          isWaiting = true
  71.                          lockObj.wait(); 
  72.                      } 
  73.                      sendObj = sendObjList.get(0); 
  74.                      os.writeObject(sendObj); 
  75.                      os.flush(); 
  76.   
  77.                      /* 发送null时,表示退出了 */ 
  78.                      if (null == sendObj) { 
  79.                          if (null != listener) { 
  80.                             listener.onExited(client.getInetAddress()); 
  81.                          } 
  82.                          break
  83.                      } 
  84.                      sendObjList.remove(0); 
  85.                   } 
  86.               } 
  87.   
  88.            } catch (SocketException e) { // Connection reset 
  89.               if (null != listener) { 
  90.                   listener.onSocketException(client.getInetAddress()); 
  91.               } 
  92.            } catch (IOException e) { 
  93.               e.printStackTrace(); 
  94.            } catch (InterruptedException e) { 
  95.               e.printStackTrace(); 
  96.            } finally { 
  97.               try { 
  98.                   if (null != os) { 
  99.                      os.close(); 
  100.                   } 
  101.                   if (null != client) { 
  102.                      client.close(); 
  103.                   } 
  104.               } catch (IOException e) { 
  105.                   e.printStackTrace(); 
  106.               } 
  107.            } 
  108.        } 
  109.   
  110.     } 
  111.   
  112.     /** 发送序列化对象 */ 
  113.     public void sendObj(Object obj) { 
  114.        /* 这个判断非必需的,记得就好 */ 
  115.        if (null != obj && !isSerializable(obj)) 
  116.            throw new IllegalArgumentException( 
  117.                   "Object needs to implement java.io.Serializable!"); 
  118.  
  119.        sendObjList.add(obj); 
  120.   
  121.        if (isWaiting) { 
  122.            synchronized (lockObj) { 
  123.               lockObj.notifyAll(); 
  124.            } 
  125.            isWaiting = false
  126.        } 
  127.     } 
  128.   
  129.     /** 判断是否序列化 */ 
  130.     private boolean isSerializable(Object obj) { 
  131.        Class<?>[] cls = obj.getClass().getInterfaces(); 
  132.        for (Class<?> clazz : cls) { 
  133.            if (clazz.getName().equals(Serializable.class.getName())) 
  134.               return true
  135.        } 
  136.        return false
  137.     } 
  138.   
  139.     /** 设置服务器监听接口 */ 
  140.     public void setOnLinkServerListener(OnLinkServerListener listener) { 
  141.        this.listener = listener; 
  142.     } 
  143.