Java BIO及實現


發現日常學習過的知識不久就會遺忘,在此只是整理並記錄一下學習筆記,做個回憶,並方便以后查閱,若有錯誤,歡迎指正

 

網絡模型: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流中,並等待客戶端返回信息,

  接受到返回信息后,則接着往下執行,若不需輸入,則釋放連接

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM