發現日常學習過的知識不久就會遺忘,在此只是整理並記錄一下學習筆記,做個回憶,並方便以后查閱,若有錯誤,歡迎指正
網絡模型:TCP/IP網絡模型是從OSI七層模型中演化來的,osi模型分為物理層,數據鏈路層,網絡層,傳輸層,會話層,表示層,應用層,
TCP/IP網絡模型分為:網絡接口層,網際層,傳輸層,應用層
我對BIO的認識: 隨着技術的發展,兩個或以上的程序必然需要進行交互,於是BIO提供了一種端到端的通信,相當於對傳輸層的一種封裝,對於開發人員而言
隱藏了傳輸的細節,將這些固定的“套路”抽象出來,提供一種端到端的通信,可以使我們更加專注於業務的開發,並且這種通訊是阻塞式的(block input output)
阻塞式:服務端啟動,等待客戶端的連接,在客戶端連接到服務端后,服務端啟動一個線程去監聽客戶端消息,客戶端發送消息,並等待服務端返回(客戶端一直阻塞),服務端收到消息,
將消息返回給客戶端,此時一次交互完成。若還需交互,則不釋放連接,客戶端再次將消息發送給服務端,並等待返回,若不需要交互,則客戶端釋放連接。
生活中例子:A聘用了B干活,A讓B去打印材料,在B去打印的期間,A一直在等待B的回來,在B沒返回時,A將不做任何事情,一直等待B的返回,直到B返回后,A才接受到材料 (一次交互完成)
如果A還需要打印,則再次讓B去打印,並等待B返回,期間什么都不干,如果不需要B去打印,就解除和B的聘用關系。直至再需要時聘用C
BIO代碼實現(參考了一些市面上的視頻資料,侵刪)
服務端:
1 package com.study.server; 2 3 import com.study.info.HostInfo; 4 5 import java.io.IOException; 6 import java.io.PrintStream; 7 import java.net.ServerSocket; 8 import java.net.Socket; 9 import java.util.Scanner; 10 import java.util.concurrent.ExecutorService; 11 import java.util.concurrent.Executors; 12 13 public class BIOEchoServer { 14 public static void main(String[] args) throws Exception{ 15 ServerSocket socket = new ServerSocket(HostInfo.PORT); 16 System.out.println("服務端已經啟動,監聽端口為:" + HostInfo.PORT); 17 boolean flag = true; 18 ExecutorService executorService = Executors.newFixedThreadPool(10); 19 while (flag){ 20 Socket client = socket.accept(); 21 executorService.submit(new EchoClientHandler(client)); 22 } 23 executorService.shutdown(); 24 socket.close(); 25 } 26 27 private static class EchoClientHandler implements Runnable{ 28 29 private Socket client; 30 private Scanner scanner; 31 private PrintStream out; 32 private boolean flag = true; 33 34 public EchoClientHandler(Socket client){ 35 this.client = client; 36 try { 37 this.scanner = new Scanner(this.client.getInputStream()); 38 this.scanner.useDelimiter("\n"); 39 this.out = new PrintStream(this.client.getOutputStream()); 40 } catch (IOException e) { 41 e.printStackTrace(); 42 } 43 } 44 45 public void run() { 46 while (this.flag){ 47 if(this.scanner.hasNext()){ 48 String var = this.scanner.next().trim(); 49 System.out.println("收到客戶端發來的"+var); 50 if("byebye".equals(var)){ 51 this.out.print("888888"); 52 this.flag = false; 53 } else { 54 out.println("【echo】" + var); 55 } 56 } 57 } 58 try { 59 this.scanner.close(); 60 this.out.close(); 61 this.client.close(); 62 } catch (IOException e) { 63 e.printStackTrace(); 64 } 65 } 66 } 67 }
客戶端:
package com.study.client; import com.study.info.HostInfo; import com.study.util.InputUtil; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class BIOEchoClient { public static void main(String[] args) throws Exception{ Socket client = new Socket(HostInfo.HOST_NAME, HostInfo.PORT); Scanner scan = new Scanner(client.getInputStream()); scan.useDelimiter("\n"); PrintStream out = new PrintStream(client.getOutputStream()); boolean flag = true; while (flag){ String inputData = InputUtil.getString("請輸入要發送的內容:").trim(); out.println(inputData); if (scan.hasNext()){ String str = scan.next(); System.out.println(str); } if ("byebye".equalsIgnoreCase(inputData)){ flag = false; } } client.close(); } }
工具包:
1 package com.study.util; 2 3 import java.io.BufferedReader; 4 import java.io.IOException; 5 import java.io.InputStreamReader; 6 7 public class InputUtil { 8 private static final BufferedReader KEYBOARD_INPUT = new BufferedReader(new InputStreamReader(System.in)); 9 10 private InputUtil(){ 11 } 12 13 public static String getString(String prompt){ 14 boolean flag = true; //數據接受標記 15 String str = null; 16 while (flag){ 17 System.out.println(prompt); 18 try { 19 str = KEYBOARD_INPUT.readLine(); // 讀取一行數據 20 if(str == null || "".equals(str)){ 21 System.out.println("數據輸入錯誤,不允許為空!"); 22 }else { 23 flag = false; 24 } 25 } catch (IOException e) { 26 e.printStackTrace(); 27 } 28 } 29 return str; 30 } 31 }
IP及端口常量:
1 package com.study.info; 2 3 public class HostInfo { 4 public static final String HOST_NAME = "localhost"; 5 public static final int PORT = 9999; 6 }
效果

代碼思路整理:
服務端:
1.通過ServerSocket創建監聽,並創建線程池
2.當ServerSocket通過accept方法接受到請求時,線程池將會分出一個線程來執行所要進行的操作
3.(分出的線程會)等待客戶端輸入完成(即客戶端安排做的事),客戶端輸入完成,則將會執行自己的處理並返回相應的結果(需要服務端來進行的運算,取數等一些操作,本例中是更改字符串)
4.服務端處理完成,則將數據返回客戶端,等待客戶端的下次輸入事件,循環3,4,直至客戶端釋放連接
客戶端:
通過Socket創建客戶端,在接受到鍵盤輸入后,將輸入信息寫入OutputStream流中,並等待客戶端返回信息,
接受到返回信息后,則接着往下執行,若不需輸入,則釋放連接
