[Java]Socket和ServerSocket學習筆記
阿新 • • 發佈:2019-02-05
對於即時類應用或者即時類的遊戲,HTTP協議很多時候無法滿足於我們的需求。這會,Socket對於我們來說就非常實用了。下面是本次學習的筆記。主要分異常型別、互動原理、Socket、ServerSocket、多執行緒這幾個方面闡述。
異常型別 在瞭解Socket的內容之前,先要了解一下涉及到的一些異常型別。以下四種類型都是繼承於IOException,所以很多之後直接彈出IOException即可。 UnkownHostException: 主機名字或IP錯誤 ConnectException: 伺服器拒絕連線、伺服器沒有啟動、(超出佇列數,拒絕連線) SocketTimeoutException: 連線超時 BindException: Socket物件無法與制定的本地IP地址或埠繫結 互動過程Socket()
Socket(InetAddress address, int port)throws UnknownHostException, IOException Socket(InetAddress address, int port, InetAddress localAddress, int localPort)throws IOException Socket(String host, int port)throws UnknownHostException, IOException Socket(String host, int port, InetAddress localAddress, int localPort)throws IOException 除去第一種不帶引數的之外,其它建構函式會嘗試建立與伺服器的連線。如果失敗會丟擲IOException錯誤。如果成功,則返回Socket物件。 InetAddress是一個用於記錄主機的類,其靜態getHostByName(String msg)可以返回一個例項,其靜態方法getLocalHost()也可以獲得當前主機的IP地址,並返回一個例項。Socket(String host, int port, InetAddress localAddress, int localPort)建構函式的引數分別為目標IP、目標埠、繫結本地IP、繫結本地埠。 Socket方法boolean半關閉Socket 很多時候,我們並不知道在獲得的輸入流裡面到底讀多長才結束。下面是一些比較普遍的方法:isConnection=socket.isConnected() && !socket.isClosed(); //判斷當前是否處於連線
- 自定義識別符號(譬如下面的例子,當受到“bye”字串的時候,關閉Socket)
- 告知讀取長度(有些自定義協議的,固定前幾個位元組表示讀取的長度的)
- 讀完所有資料
- 當Socket呼叫close的時候關閉的時候,關閉其輸入輸出流
public void service(){ while(true){ Socket socket=null; try{ socket=serverSocket.accept();//從連線佇列中取出一個連線,如果沒有則等待 System.out.println("新增連線:"+socket.getInetAddress()+":"+socket.getPort()); ...//接收和傳送資料 }catch(IOException e){e.printStackTrace();}finally{ try{ if(socket!=null) socket.close();//與一個客戶端通訊結束後,要關閉Socket }catch(IOException e){e.printStackTrace();} } } }多執行緒的ServerSocket 多執行緒的好處不用多說,而且大多數的場景都是多執行緒的,無論是我們的即時類遊戲還是IM,多執行緒的需求都是必須的。下面說說實現方式:
- 主執行緒會迴圈執行ServerSocket.accept();
- 當拿到客戶端連線請求的時候,就會將Socket物件傳遞給多執行緒,讓多執行緒去執行具體的操作;
public void service(){ while(true){ Socket socket=null; try{ socket=serverSocket.accept(); //主執行緒獲取客戶端連線 Thread workThread=new Thread(new Handler(socket)); //建立執行緒 workThread.start(); //啟動執行緒 }catch(Exception e){ e.printStackTrace(); } } }當然這裡的重點在於如何實現Handler這個類。Handler需要實現Runnable介面:
class Handler implements Runnable{ private Socket socket; public Handler(Socket socket){ this.socket=socket; } public void run(){ try{ System.out.println("新連線:"+socket.getInetAddress()+":"+socket.getPort()); Thread.sleep(10000); }catch(Exception e){e.printStackTrace();}finally{ try{ System.out.println("關閉連線:"+socket.getInetAddress()+":"+socket.getPort()); if(socket!=null)socket.close(); }catch(IOException e){ e.printStackTrace(); } } } }
當然是先多執行緒還有其它的方式,譬如執行緒池,或者JVM自帶的執行緒池都可以。這裡就不說明了。