天天看點

Java Socket基礎(三)

<a target="_blank" href="http://vaero.blog.51cto.com/4350852/893837">Java Socket基礎(一)</a>

<a target="_blank" href="http://vaero.blog.51cto.com/4350852/893844">Java Socket基礎(二)</a>

2.3)LinkServer2.java

/** 

 * 開啟伺服器,長連接配接各個Socket,主動發送資料 

 * 

 * @author Join 

 */ 

public class LinkServer2 extends Thread { 

    /** 服務端口 */ 

    private int port; 

    /** 服務套接字 */ 

    private ServerSocket mServerSocket; 

    /** 伺服器監聽接口 */ 

    private OnLinkServerListener listener; 

    /** 用戶端套接字集合 */ 

    private ArrayList&lt;Socket&gt; clientList; 

    /** 用戶端的輸出流集合 */ 

    private ArrayList&lt;ObjectOutputStream&gt; osList; 

    public LinkServer2(int port) { 

       this.port = port; 

       clientList = new ArrayList&lt;Socket&gt;(); 

       osList = new ArrayList&lt;ObjectOutputStream&gt;(); 

    } 

    @Override 

    public void run() { 

       try { 

           mServerSocket = new ServerSocket(port); // 建立本地特定端口伺服器套接字 

           Socket client = null; 

           while (true) { 

              client = mServerSocket.accept(); // 接收連接配接的套接字 

              if (null != listener) { 

                  listener.onClientConnected(client.getInetAddress()); 

              } 

              clientList.add(client); 

              osList.add(new ObjectOutputStream(client.getOutputStream())); // 增加連接配接的輸出流 

           } 

       } catch (BindException e) { // 端口使用中 

           if (null != listener) { 

              listener.onBindException(); 

       } catch (IOException e) { 

           e.printStackTrace(); 

       } 

    /** 發送序列化對象 */ 

    public void sendObj(Object obj) { 

       /* 這個判斷非必需的,記得就好 */ 

       if (null != obj &amp;&amp; !isSerializable(obj)) 

           throw new IllegalArgumentException( 

                  "Object needs to implement java.io.Serializable!"); 

       ObjectOutputStream out = null; 

       for (int i = 0; i &lt; osList.size(); i++) { 

           try { 

              out = osList.get(i); 

              out.writeObject(obj); 

              out.flush(); 

              /* 發送null時,表示退出了 */ 

              if (null == obj) { 

                  if (null != listener) { 

                     listener.onExited(clientList.get(i).getInetAddress()); 

                  } 

                  closeSocket(i); // 關閉目前Socket 

                  i--; // 少了個記得減 

           } catch (SocketException e) { // Connection reset 

                  listener.onSocketException(clientList.get(i) 

                         .getInetAddress()); 

              closeSocket(i); // 關閉目前Socket 

              i--; // 少了個記得減 

           } catch (IOException e) { 

              e.printStackTrace(); 

    /** 關閉某個Socket */ 

    private void closeSocket(int index) { 

           osList.get(index).close(); 

           osList.remove(index); 

           clientList.get(index).close(); 

           clientList.remove(index); 

       } catch (IOException e1) { 

           e1.printStackTrace(); 

    /** 判斷是否序列化 */ 

    private boolean isSerializable(Object obj) { 

       Class&lt;?&gt;[] cls = obj.getClass().getInterfaces(); 

       for (Class&lt;?&gt; clazz : cls) { 

           if (clazz.getName().equals(Serializable.class.getName())) 

              return true; 

       return false; 

    /** 設定伺服器監聽接口 */ 

    public void setOnLinkServerListener(OnLinkServerListener listener) { 

       this.listener = listener; 

<b>二、短連接配接通信</b>

         用戶端請求一次,建立一次Socket,完成後即可關閉。服務端通過accept()等待。

<b>1</b><b>)對象消息</b>

         用戶端發送對象,服務端接受對象,很簡單的例子。

1.1)EasyClient.java

 * 每次連接配接伺服器發送一個消息 

 *  

public class EasyClient { 

    /** 套接字位址 */ 

    private SocketAddress address; 

    /** 逾時時間 */ 

    private int timeout; 

    /** 用戶端監聽接口 */ 

    private OnClientListener listener; 

    public EasyClient(String host, int port, int timeout) { 

        this.address = new InetSocketAddress(host, port); 

        this.timeout = timeout; 

    /** 

     * 發送一個消息 

     *  

     * @param obj 對象消息 

     */ 

    public boolean sendMessage(Object obj) { 

        boolean result = false; 

        Socket socket = null; 

        try { 

            socket = new Socket(); 

            socket.connect(address, timeout); 

            if (null != listener) { 

                listener.onConnected(); 

            } 

            result = sendMessage(socket, obj); 

        } catch (ConnectException e) { // 拒絕連接配接 

                listener.onConnectException(); 

        } catch (SocketTimeoutException e) { // 連接配接逾時 

                listener.onTimeoutException(); 

        } catch (IOException e) { 

            e.printStackTrace(); 

        } finally { 

            try { 

                if (null != socket) { 

                    socket.close(); // 關閉Socket 

                    socket = null; 

                } 

            } catch (IOException e) { 

                e.printStackTrace(); 

        } 

        return result; 

    /** 通過Socket發送obj消息 */ 

    private boolean sendMessage(Socket socket, Object obj) { 

        ObjectOutputStream os = null; 

            os = new ObjectOutputStream(socket.getOutputStream()); 

            os.writeObject(obj); 

            os.flush(); 

                listener.onMessageSent(obj); 

            result = true; 

        } catch (SocketException e) { // Connection reset 

                listener.onSocketException(); 

                if (null != os) { 

                    os.close(); 

    /** 設定用戶端監聽接口 */ 

    public void setOnClientListener(OnClientListener listener) { 

        this.listener = listener; 

1.2)EasyServer.java<b></b>

public class EasyServer extends Thread { 

    private OnServerListener listener; 

    public EasyServer(int port) { 

        this.port = port; 

            mServerSocket = new ServerSocket(port); // 建立本地特定端口伺服器套接字 

            Socket socket = null; 

            while (true) { 

                socket = mServerSocket.accept(); // 接收連接配接的套接字 

                receiveMessage(socket); // 接收socket處理消息 

        } catch (BindException e) { // 端口使用中 

                listener.onBindException(); 

    /** 接收處理每個Socket資訊 */ 

    private void receiveMessage(Socket socket) { 

        ObjectInputStream is = null; 

            is = new ObjectInputStream(new BufferedInputStream( 

                    socket.getInputStream())); 

            Object obj = is.readObject(); 

                listener.onReceive(socket.getInetAddress(), obj); 

                listener.onSocketException(socket.getInetAddress()); 

        } catch (ClassNotFoundException e) { 

                if (null != is) { 

                    is.close(); 

                    socket.close(); 

    public void setOnServerListener(OnServerListener listener) { 

<b>三、後記</b>

         恩,哦,socket還有個比較常用的是setSoTimeout(),在read()阻塞逾時會報SocketTimeoutException,catch住處理即可。

         ps:老遇到8W備援字元,拆着拆着就三個了==!

<a href="http://down.51cto.com/data/2360758" target="_blank">附件:http://down.51cto.com/data/2360758</a>

     本文轉自winorlose2000 51CTO部落格,原文連結:http://blog.51cto.com/vaero/893847,如需轉載請自行聯系原作者