网络——实现服务器
【0】README
0.1) 本文描述部分轉自 core java volume 2 , 旨在理解 網絡——實現服務器 的基礎知識 ;
0.2) for source code, please visit https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter3/EchoServer.java + https://github.com/pacosonTang/core-java-volume/blob/master/coreJavaAdvanced/chapter3/ThreadedEchoServer.java
【1】實現服務器
1)看個荔枝:我們的服務器可以向client 發送信息;
2)服務器描述:
- 2.1)一旦啟動服務器程序, 它便等待某個客戶端連接到他的端口;
- 2.2)ServerSocket 類用于建立服務器套結字, 如:
- 2.3)用于建立一個監控8189的服務器,如:
- 2.4)上述代碼用于告訴程序不停地等待, 直到有client就連接到這個端口;
- 2.5)如果有client 連接到 server 的 8189端口, 可以使用這個對象來得到輸入流和輸出流, 如:
- 2.6)服務器發送給服務器輸出流的所有信息都會成為 client 程序的輸入, 同時來自 client 程序的所有輸出都會被包含在 服務器輸入流中;
- 2.7)因為本章中的程序,我們都要通過套接字來發送文本, 所以我們將流轉換為掃描器和寫入器:
- 2.8)以下代碼將給client 發送一條信息:
- 2.9)代碼最后,我們關閉了連接進來的套接字:
Conclusion) 這就是大致情況。 每一個server 程序, 比如一個 HTTP web 服務器, 都不間斷地執行這個循環:
- C1)通過輸入數據流從客戶端接收一個命令;
- C2)解碼這個客戶端命令;
- C3) 收集客戶端所請求的信息;
- C4) 通過輸出數據流發送消息給客戶端;
【2】為多個客戶端服務(有多個client 同時連接到我們的server上)
1)假設我們希望有多個客戶端同時連接到我們的server上, 每當程序建立一個新的套接字連接, 即當調用accept 時, 將啟動一個新線程來處理服務器和該客戶端間的連接, 而主程序將立即返回并等待下一個連接;
2)為了實現這個機制, 服務器應該具有以下代碼的循環操作:
- 2.1)ThreadEchoHandler 類實現了 Runnable接口,而在它的run方法中包含了與client 循環通信的代碼:
- 2.2)由于每一個連接都會啟動一個新的線程,因而多個client 就可以同時連接到 server了;
3)看個荔枝(做個測試):
- step1)編譯和運行服務器程序;
- step2)打開 數個 telnet 窗口;
- step3)切換窗口,鍵入命令(telnet localhost(or your visitorial host) port )。注意你可以同時通過這些窗口進行通信;
- step4) 完成之后,切換到你啟動服務器的窗口, 使用ctrl +c 強制關閉它;
【3】半關閉
1)引入半關閉的原因: 半關閉提供了這樣一種能力: 套接字連接的一端可以終止其輸出,同時仍舊可以接收來自另一端的數據;
2)problem+solution
- 2.1)problem: 這是一種很典型的case。 例如,我們在向服務器傳輸數據, 但是并不知道要傳輸多少數據。在向文件寫數據時,我們只需在數據寫入后關閉文件即可。 但是,如果關閉一個套接字,那么與服務器的連接將立即斷開, 因而也就無法讀取服務器的響應了;
- 2.2)solution:使用半關閉就可以解決。 可以通過關閉一個套接字的輸出流來表示發送給服務器的請求數據已經結束, 但是必須保持輸入流處于打開狀態;
3)以下代碼演示了 如何在客戶端使用半關閉方法:
Socket socket = new Socket(host, port); Scanner in = new Scanner(socket.getInputStream() ); PrintWriter writer = new PrintWriter(socket.getOutputStream()); writer.print(...); writer.flush(); socket.shutdownOutput(); // client 關閉 outputStream,但是保持inputStream 處于開啟狀態; while(in.hasNextLine() != null) {String line = in.nextLine();...... } socket.close();- 3.1)服務器端將讀取輸入信息,直到到達輸入流的結尾, 然后它再發送響應; 然后上述代碼中的while 循環讀取 server 的response info;
總結
- 上一篇: 九点打一字 谜语简介
- 下一篇: 常见 Java 字节码 指令 助记符