1. 程式人生 > >Socket和ServerSocket學習筆記

Socket和ServerSocket學習筆記

對於即時類應用或者即時類的遊戲,HTTP協議很多時候無法滿足於我們的需求。這會,Socket對於我們來說就非常實用了。下面是本次學習的筆記。主要分異常型別、互動原理、Socket、ServerSocket、多執行緒這幾個方面闡述。

異常型別 在瞭解Socket的內容之前,先要了解一下涉及到的一些異常型別。以下四種類型都是繼承於IOException,所以很多之後直接彈出IOException即可。 UnkownHostException:      主機名字或IP錯誤 ConnectException:        伺服器拒絕連線、伺服器沒有啟動、(超出佇列數,拒絕連線) SocketTimeoutException:      連線超時 BindException:          Socket物件無法與制定的本地IP地址或埠繫結 互動過程
Socket與ServerSocket的互動,下面的圖片我覺得已經說的很詳細很清楚了。

在客戶/伺服器通訊模式中,伺服器端需要建立監聽特定埠的ServerSocket,ServerSocket負責接收客戶連線請求。本章首先介紹ServerSocket類的各個構造方法,以及成員方法的用法,接著介紹伺服器如何用多執行緒來處理與多個客戶的通訊任務。

本章提供執行緒池的一種實現方式。執行緒池包括一個工作佇列和若干工作執行緒。伺服器程式向工作佇列中加入與客戶通訊的任務,工作執行緒不斷從工作佇列中取出任務並執行它。本章還介紹了Java.util.concurrent包中的執行緒池類的用法,在伺服器程式中可以直接使用它們。

3.1  構造ServerSocket

ServerSocket的構造方法有以下幾種過載形式:

◆ServerSocket()throws IOException 
◆ServerSocket(int port) throws IOException 
◆ServerSocket(int port, int backlog) throws IOException
◆ServerSocket(int port, int backlog, InetAddress bindAddr) throws IOException   

在以上構造方法中,引數port指定伺服器要繫結的埠(伺服器要監聽的埠),引數backlog指定客戶連線請求佇列的長度,引數bindAddr指定伺服器要繫結的IP地址。

3.1.1  繫結埠

除了第一個不帶引數的構造方法以外,其他構造方法都會使伺服器與特定埠繫結,該埠由引數port指定。例如,以下程式碼建立了一個與80埠繫結的伺服器:

  1. ServerSocket serverSocket=new ServerSocket(80);  
◆埠已經被其他伺服器程序佔用;如果執行時無法繫結到80埠,以上程式碼會丟擲IOException,更確切地說,是丟擲BindException,它是IOException的子類。BindException一般是由以下原因造成的:

◆在某些作業系統中,如果沒有以超級使用者的身份來執行伺服器程式,那麼作業系統不允許伺服器繫結到1~1023之間的埠。

如果把引數port設為0,表示由作業系統來為伺服器分配一個任意可用的埠。由作業系統分配的埠也稱為匿名埠。對於多數伺服器,會使用明確的埠,而不會使用匿名埠,因為客戶程式需要事先知道伺服器的埠,才能方便地訪問伺服器。在某些場合,匿名埠有著特殊的用途,本章3.4節會對此作介紹。

3.1.2  設定客戶連線請求佇列的長度

當伺服器程序執行時,可能會同時監聽到多個客戶的連線請求。例如,每當一個客戶程序執行以下程式碼:

  1. Socket socket=new Socket(www.javathinker.org,80);  

就意味著在遠端www.javathinker.org主機的80埠上,監聽到了一個客戶的連線請求。管理客戶連線請求的任務是由作業系統來完成的。作業系統把這些連線請求儲存在一個先進先出的佇列中。許多作業系統限定了佇列的最大長度,一般為50。當佇列中的連線請求達到了佇列的最大容量時,伺服器程序所在的主機會拒絕新的連線請求。只有當伺服器程序通過ServerSocket的accept()方法從佇列中取出連線請求,使佇列騰出空位時,佇列才能繼續加入新的連線請求。

對於客戶程序,如果它發出的連線請求被加入到伺服器的佇列中,就意味著客戶與伺服器的連線建立成功,客戶程序從Socket構造方法中正常返回。如果客戶程序發出的連線請求被伺服器拒絕,Socket構造方法就會丟擲ConnectionException。

ServerSocket構造方法的backlog引數用來顯式設定連線請求佇列的長度,它將覆蓋作業系統限定的佇列的最大長度。值得注意的是,在以下幾種情況中,仍然會採用作業系統限定的佇列的最大長度:

◆backlog引數的值大於作業系統限定的佇列的最大長度;
◆backlog引數的值小於或等於0;
◆在ServerSocket構造方法中沒有設定backlog引數。

以下例程3-1的Client.java和例程3-2的Server.java用來演示伺服器的連線請求佇列的特性。

例程3-1  Client.java

  1. import java.net.*;  
  2. publicclass Client {  
  3.   publicstaticvoid main(String args[])throws Exception{  
  4.     finalint length=100;  
  5.     String host="localhost";  
  6.     int port=8000;  
  7.     Socket[] sockets=new Socket[length];  
  8.     for(int i=0;i<length;i++){     // 試圖建立100次連線
  9.       sockets[i]=new Socket(host, port);  
  10.       System.out.println("第"+(i+1)+"次連線成功");  
  11.     }  
  12.     Thread.sleep(3000);  
  13.     for(int i=0;i<length;i++){  
  14.       sockets[i].close();      //斷開連線
  15.     }   
  16.   }  
  17. }  

  1. import java.io.*;  
  2. import java.net.*;  
  3. publicclass Server {  
  4.   privateint port=8000;  
  5.   private ServerSocket serverSocket;  
  6.   public Server() throws IOException {  
  7.     serverSocket = new ServerSocket(port,3);    //連線請求佇列的長度為3
  8.     System.out.println("伺服器啟動");  
  9.   }  
  10.   publicvoid service() {  
  11.     while (true) {  
  12.       Socket socket=null;  
  13.       try {  
  14.         socket = serverSocket.accept();     //從連線請求佇列中取出一個連線         
  15.         System.out.println("New connection accepted " +  
  16.         socket.getInetAddress() + ":" +socket.getPort());  
  17.       }catch (IOException e) {  
  18.          e.printStackTrace();  
  19.       }finally {  
  20.          try{  
  21.            if(socket!=null)socket.close();  
  22.          }catch (IOException e) {e.printStackTrace();}  
  23.       }  
  24.     }  
  25.   }  
  26.   publicstaticvoid main(String args[])throws Exception {  
  27.     Server server=new Server();  
  28.     Thread.sleep(60000*10);      //睡眠10分鐘
  29.     //server.service();
  30.   }  
  31. }  

例程3-2  Server.java

Client試圖與Server進行100次連線。在Server類中,把連線請求佇列的長度設為3。這意味著當佇列中有了3個連線請求時,如果Client再請求連線,就會被Server拒絕。下面按照以下步驟執行Server和Client程式。

(1)把Server類的main()方法中的“server.service();”這行程式程式碼註釋掉。這使得伺服器與8000埠繫結後,永遠不會執行serverSocket.accept()方法。這意味著佇列中的連線請求永遠不會被取出。先執行Server程式,然後再執行Client程式,Client程式的列印結果如下:

  1. 1次連線成功  
  2. 2次連線成功  
  3. 3次連線成功  
  4. Exception in thread "main" java.net.ConnectException: Connection refused: connect          
  5.         at java.net.PlainSocketImpl.socketConnect(Native Method)  
  6.         at java.net.PlainSocketImpl.doConnect(Unknown Source)  
  7.         at java.net.PlainSocketImpl.connectToAddress(Unknown Source)  
  8.         at java.net.PlainSocketImpl.connect(Unknown Source)  
  9.         at java.net.SocksSocketImpl.connect(Unknown Source)  
  10.         at java.net.Socket.connect(Unknown Source)  
  11.         at java.net.Socket.connect(Unknown Source)  
  12.         at java.net.Socket.(Unknown Source)  
  13.         at java.net.Socket.(Unknown Source)  
  14.         at Client.main(Client.java:10)  
(2)把Server類的main()方法按如下方式修改:從以上列印結果可以看出,Client與Server在成功地建立了3個連線後,就無法再建立其餘的連線了,因為伺服器的佇列已經滿了。
  1. publicstaticvoid main(String args[])throws Exception {                   
  2.     Server server=new Server();  
  3.     //Thread.sleep(60000*10);  //睡眠10分鐘
  4.     server.service();  
  5.   }  

作了以上修改,伺服器與8 000埠繫結後,就會在一個while迴圈中不斷執行serverSocket.accept()方法,該方法從佇列中取出連線請求,使得佇列能及時騰出空位,以容納新的連線請求。先執行Server程式,然後再執行Client程式,Client程式的列印結果如下:

  1. 1次連線成功  
  2. 2次連線成功  
  3. 3次連線成功  
  4. …  
  5. 100次連線成功  

從以上列印結果可以看出,此時Client能順利與Server建立100次連線。

3.1.3  設定繫結的IP地址

如果主機只有一個IP地址,那麼預設情況下,伺服器程式就與該IP地址繫結。ServerSocket的第4個構造方法ServerSocket(int port, int backlog, InetAddress bindAddr)有一個bindAddr引數,它顯式指定伺服器要繫結的IP地址,該構造方法適用於具有多個IP地址的主機。假定一個主機有兩個網絡卡,一個網絡卡用於連線到Internet, IP地址為222.67.5.94,還有一個網絡卡用於連線到本地區域網,IP地址為192.168.3.4。如果伺服器僅僅被本地區域網中的客戶訪問,那麼可以按如下方式建立ServerSocket:

    相關推薦

    SocketServerSocket學習筆記

    對於即時類應用或者即時類的遊戲,HTTP協議很多時候無法滿足於我們的需求。這會,Socket對於我們來說就非常實用了。下面是本次學習的筆記。主要分異常型別、互動原理、Socket、ServerSocket、多執行緒這幾個方面闡述。 異常型別 在瞭解Socket的內容之前,先要了解一下涉及到的一

    [Java]SocketServerSocket學習筆記

    對於即時類應用或者即時類的遊戲,HTTP協議很多時候無法滿足於我們的需求。這會,Socket對於我們來說就非常實用了。下面是本次學習的筆記。主要分異常型別、互動原理、Socket、ServerSocket、多執行緒這幾個方面闡述。 異常型別 在瞭解Socket的內容之前,先要了解一下涉及到的一些異常型別

    [Java]SocketServerSocket學習

    對於即時類應用或者即時類的遊戲,HTTP協議很多時候無法滿足於我們的需求。這會,Socket對於我們來說就非常實用了。 下面是本次學習的筆記。主要分異常型別、互動原理、Socket、ServerSocket、多執行緒這幾個方面闡述。 異常型別 在瞭解Socket的內容

    安卓 java 學習筆記

    點擊 進行 sha ring text div -a 變量 tco 1、訪問權限為 private 的成員變量或方法,需要執行setAccessible() 方法,並將入口參數設置為 true; 否則不允許訪問。 2、為了保證線程的安全,可以使用同步塊 synchron

    流暢的pythoncookbook學習筆記(一)

    構造函數 推導 笛卡爾 expr 列表推導 叠代 建立 笛卡兒 imp 1.數據結構 1.1 內置序列類型   四種序列類型:   1.容器序列:list、tuple和collections.deque   2.扁平序列:str、bytes、bytearray、memory

    流暢的pythoncookbook學習筆記(五)

    pytho col () 學習 util 學習筆記 取出 minute python 1.隨機選擇   python中生成隨機數使用random模塊。   1.從序列中隨機挑選元素,使用random.choice() >>> import random

    流暢的pythoncookbook學習筆記(八)

    不可變 pri 列表 改變 如果 book 影響 color print 1.函數的默認參數必須不可變   如果函數的默認參數為可變的對象,那麽默認參數在函數外被修改也會影響到函數本身的。 >>> def spam(a, b=None): # b要為不

    神經網絡深度學習 筆記

    ack 參數 一個 bsp 感知機 信號 叠代 前饋型神經網絡 pro 人工神經網絡(ann) 模擬的是 生物神經網絡(bnn) ann 一般也叫 前饋型神經網絡 : 各神經元只接受前一級輸入,並輸出到下一級,無反饋 應該也有反饋型神經網絡?? ann一般使用b

    python——元組字典學習筆記

    deepcopy 例子 [] items 是個 rev put 次數 style 1.count返回值的次數 list=[2,2,2,3,3,3,3,4,4,4] a={} for i in list: if list.count(i)>1:

    thissuper的區別應用 學習筆記

    pri xtend In ID AR super string print pub A:this和super都代表什麽 this:代表當前對象的引用,誰來調用我,我就代表誰 super:代表當前對象父類的引用 B:this和super的使用區別 a:調用成員變量 t

    JSPServlet學習筆記1 - 訪問配置

    技術分享 exception print pack ping 分享 tdi 1.0 nds 1. 訪問WebContent目錄下的JSP文件 在WebContent中新建一個 test.jsp 文件 <%@ page language="java" co

    工廠方法模式的概述使用學習筆記

    每次 extend ride xtend tor 自己 pre ide 抽象類 A:工廠方法模式概述 工廠方法模式中抽象工廠類負責定義創建對象的接口,具體對象的創建工作由繼承抽象工廠的具體類實現。 B:優點 客戶端不需要在負責對象的創建,從而明確了各個類的職責,如果有

    線程池的概述使用學習筆記

    pre 應該 code call adp 關閉 產生 提高 single A:線程池概述程序啟動一個新線程成本是比較高的,因為它涉及到要與操作系統進行交互。而使用線程池可以很好的提高性能,尤其是當程序中要創建大量生存期很短的線程時,更應該考慮使用線程池。線程池裏的每一個線程

    網路程式設計(InetAddress類、SocketServerSocket、實現客戶端伺服器之間的雙向通訊)

    網路程式設計的底層是IO,通過IO將一臺計算機中的資料傳送到另一臺計算機中。傳送的時候,要知道接受方的地址,該地址即為IP地址。知道IP地址後即可進行傳送。A向B發訊息,訊息是發過去了,但是B要怎樣接受呢?因此定義了埠,B監聽了A所使用的埠。A發的訊息中含有埠號,當B接受到訊息時,知道了埠號

    【學會Matlab走遍天下】如何畫正弦餘弦曲線學習筆記

    常用命令: clc %清屏 clear + 變數 %將變數擦除 註釋符:% 矩陣建立 邏輯語法 sum=0;i=1; while(i<=100) sum=sum+i;i=i+1; sum

    AJAXJSON學習筆記

    1.關係對映 - 多對多 物件名 = db.Table( '關聯表名', db.Column('id',db.Integer,primary_key=True), db.Column('外來鍵列名',db.TYPE,db.ForeignKey('主表.主鍵')), db.Column('外來鍵列名',db.T

    htmlcss學習筆記(二)

    1表格 1.1table tr td 1.2表格屬性 width border align="center" cellspacing 單元格邊框和單元格邊框之間的距離 cellpadding 單元格內容與單元格邊框之間的距離 *三參為0 border cellspaci

    C++類物件學習筆記(3)

    1.初始化列表 a.建構函式體賦值 在建立物件時,編譯器可以通過呼叫建構函式,給物件中各個成員變數一個合適的初始值。但是雖然建構函式呼叫之後,物件中已經有了一個初始值,但是不能將其稱作為類物件成員的

    AlexNetVGG學習筆記

    AlexNet 2012年,Alex Krizhevsky(Hinton的學生)提出了AlexNet,它可以看做是LeNet的一個更深更寬版本。 這就是Gradient-Based Learning Applied to Document Recognition論文裡

    x i l i n x -selectioclocking學習筆記

      最近做高速視訊影象採集相關的工作,需要對FPGA的selectio以及clocking資源有足夠的瞭解,於是把xilinx的ug381,ug382, xapp1064文件閱讀了一遍, 結合實際除錯中遇到的問題,總結了如下要點。   1, selectio sp