• <noscript id="e0iig"><kbd id="e0iig"></kbd></noscript>
  • <td id="e0iig"></td>
  • <option id="e0iig"></option>
  • <noscript id="e0iig"><source id="e0iig"></source></noscript>
  • netty權威指南學習筆記一——NIO入門(1)BIO

      公司的一些項目采用了netty框架,為了加速適應公司開發,本博主認真學習netty框架,前一段時間主要看了看書,發現編程這東西,不上手還是覺得差點什么,于是為了加深理解,深入學習,本博主還是決定多動手,一方面記錄一些總結性的思考性東西,另一方面也為日后復習查看留下一些東西。

      那么廢話少說,現在開始,首先在進入netty學習之前,我們是要認識一下IO并引出NIO的概念。

      與IO相關的幾種編程及特點分為:

    編程類別 特點
    傳統BIO編程

    典型的一請求一應答模型,一個請求新建一個線程,應答完成線程銷毀,線程個數和客戶端并發訪問呈現1:1的正比關系,當線程數膨脹之后,虛擬機性能下降明顯,隨著并發量繼續增大,線程耗盡就會出現線程堆棧溢出,創建新線程失敗,并最終宕機。該模型無法滿足高性能高并發的場景。

    偽異步IO編程

    偽異步IO是對BIO的優化,引入線程池和消息隊列,改善了傳統BIO編程,但是其底層仍然是BIO模型,該模型引入線程池后界定了線程的數量,N個線程處理M個客戶端請求,M可以遠遠大于N,線程池靈活調配線程資源,有最大線程數限制,避免了一個客戶端請求創建一個線程的弊端,不會發生高并發訪問下的線程資源耗盡而造成堆棧溢出或宕機的問題。

    其不利因素是當一個客戶端請求沒有處理完成時,如IO讀寫或網絡慢時,會造成任務隊列中的任務一直處于等待狀態,被阻塞了。當線程池中所有線程都滿程處于阻塞狀態時,就無法接收客戶端新的請求,請求總是超時,此時可以認為是系統崩潰。

    NIO編程

    NIO模型引入了緩沖區Buffer,所有數據的讀寫都是用緩沖區處理的。引入channel通道,和selector多路復用器。

    客戶端發起的連接操作是異步的,可以通過在多路復用器注冊OP_CONNECT等待后續結果,不需要像之前的客戶端那樣被同步阻塞,

    socketchannel的讀寫都是一步的,如果沒有可以讀寫的數據他不會同步等待,直接返回,這樣I/O通信線程就可以處理其他的鏈路,不需要同步等待這個鏈路可用;

    Selector線程可以同時處理成千上萬個客戶端連接,而且性能不會隨客戶端的增加而線性下降,非常適合高性能、高負載的網絡服務器。

    AIO編程

    AIO是NIO2.0,它引入了異步通道概念,提供了異步文件通道和異步套接字通道的實現。異步通道提供了java.util.concurrent.Future類來表示異步操作的結果。

    在執行異步操作時候傳入一個java.io.channels.

    CompletionHandler接口的實現類作為操作完成的回調。

    NIO2.0的異步套接字通道是真正的異步非阻塞I/O,它不需要通過多路復用器Selector對注冊的通道進行輪詢操作即可實現異步讀寫,從而簡化了NIO的編程模型。

    現在看看逐個看看相關模型和代碼:

    BIO模型

     

    傳統的BIO代碼 時間服務端

    package com.example.biodemo;
    
    
    import java.io.*;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TimeServer {
        public static void main(String[] args) throws IOException {
            int port = 8090;
            if (args != null && args.length > 0) {
                try {
                    port = Integer.valueOf(args[0]);
                } catch (NumberFormatException e) {
                    port = 8090;
                }
            }
            ServerSocket server = null;
            try {
                server = new ServerSocket(port);
                System.out.println("the timeServer is start in port :" + port);
                Socket socket = null;
                while (true) {
                    socket = server.accept();
                    new Thread(new TimeServerHandler(socket)).start();
                }
            } finally {
                if (server != null) {
                    System.out.println("the time server close");
                    server.close();
                    server = null;
                }
            }
    
        }
    }
    

    傳統BIO 時間處理

    package com.example.biodemo;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.io.PrintWriter;
    import java.net.Socket;
    
    public class TimeServerHandler implements Runnable {
        private Socket socket;
    
        public TimeServerHandler(Socket socket) {
            this.socket = socket;
        }
    
        @Override
        public void run() {
            BufferedReader in = null;
            PrintWriter out = null;
            try {
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                out = new PrintWriter(this.socket.getOutputStream(), true);
                String currentTime = null;
                String body = null;
                while (true) {
                    body = in.readLine();
                    if (body == null) {
                        break;
                    }
                    System.out.println("the time server receive order:" + body);
                    currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date(System.currentTimeMillis()).toString() : "bad order";
                    out.println(currentTime);
    
                }
            } catch (Exception e) {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException el) {
                        el.printStackTrace();
                    }
                }
                if (out != null) {
                    out.close();
                    out = null;
                }
                if (this.socket != null) {
                    try {
                        this.socket.close();
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                    this.socket = null;
                }
            }
        }
    }
    

      客戶端代碼

     1 package com.example.biodemo;
     2 
     3 import java.io.*;
     4 import java.net.Socket;
     5 
     6 public class TimeClient {
     7     public static void main(String[] args) {
     8         int port = 8090;
     9         if (args != null && args.length > 0) {
    10             try {
    11                 port = Integer.valueOf(args[0]);
    12             } catch (NumberFormatException ne) {
    13                 port = 8090;
    14             }
    15         }
    16         Socket socket = null;
    17         BufferedReader in = null;
    18         PrintWriter out = null;
    19         try {
    20             socket = new Socket("127.0.0.1", port);
    21             System.out.println(socket.getInputStream());
    22             in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    23             out = new PrintWriter(socket.getOutputStream(), true);
    24             out.println("QUERY TIME ORDER");
    25             System.out.println("send order 2 server succeed.");
    26             String resp = in.readLine();
    27             System.out.println("now is :" + resp);
    28         } catch (IOException e1) {
    29 
    30         } finally {
    31             if (out != null) {
    32                 out.close();
    33                 out = null;
    34             }
    35 
    36             if (in != null) {
    37                 try {
    38                     in.close();
    39                 } catch (IOException e2) {
    40                     e2.printStackTrace();
    41                 }
    42                 in = null;
    43                 if (socket != null) {
    44                     try {
    45                         socket.close();
    46                     } catch (IOException e3) {
    47                         e3.printStackTrace();
    48                     }
    49 
    50                 }
    51                 socket = null;
    52             }
    53 
    54 
    55         }
    56     }
    57 }

    啟動服務端

    啟動客戶端

    再看看服務端

    整個過程是:服務端先在某一端口啟動服務,本博主是在8090上啟動,啟動后,客戶端啟動,發送請求,請求被服務端接收后,進行邏輯處理,并將邏輯處理結果返回,這里的邏輯處理結果是當前時間,返回的結果客戶端接收后顯示出來。這就是一個典型的BIO模型。

    版權聲明:本文為zuixiaoyao_001原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
    本文鏈接:https://blog.csdn.net/zuixiaoyao_001/article/details/80972546

    智能推薦

    NIO與Netty-1-BIO

    NIO與Netty-1-BIO 文章目錄 NIO與Netty-1-BIO 示例 BIO阻塞模型 ServerSocket源碼解讀 ServerSocket創建流程 ServerSocket.accept()解讀 Socket中InputStream解讀 InputStream獲取流程 SocketInputStream.read(byte b[]) 對應的操作系統方法 BIO是同步阻塞IO,在服務...

    HTML中常用操作關于:頁面跳轉,空格

    1.頁面跳轉 2.空格的代替符...

    freemarker + ItextRender 根據模板生成PDF文件

    1. 制作模板 2. 獲取模板,并將所獲取的數據加載生成html文件 2. 生成PDF文件 其中由兩個地方需要注意,都是關于獲取文件路徑的問題,由于項目部署的時候是打包成jar包形式,所以在開發過程中時直接安照傳統的獲取方法沒有一點文件,但是當打包后部署,總是出錯。于是參考網上文章,先將文件讀出來到項目的臨時目錄下,然后再按正常方式加載該臨時文件; 還有一個問題至今沒有解決,就是關于生成PDF文件...

    電腦空間不夠了?教你一個小秒招快速清理 Docker 占用的磁盤空間!

    Docker 很占用空間,每當我們運行容器、拉取鏡像、部署應用、構建自己的鏡像時,我們的磁盤空間會被大量占用。 如果你也被這個問題所困擾,咱們就一起看一下 Docker 是如何使用磁盤空間的,以及如何回收。 docker 占用的空間可以通過下面的命令查看: TYPE 列出了docker 使用磁盤的 4 種類型: Images:所有鏡像占用的空間,包括拉取下來的鏡像,和本地構建的。 Con...

    requests實現全自動PPT模板

    http://www.1ppt.com/moban/ 可以免費的下載PPT模板,當然如果要人工一個個下,還是挺麻煩的,我們可以利用requests輕松下載 訪問這個主頁,我們可以看到下面的樣式 點每一個PPT模板的圖片,我們可以進入到詳細的信息頁面,翻到下面,我們可以看到對應的下載地址 點擊這個下載的按鈕,我們便可以下載對應的PPT壓縮包 那我們就開始做吧 首先,查看網頁的源代碼,我們可以看到每一...

    猜你喜歡

    Linux C系統編程-線程互斥鎖(四)

    互斥鎖 互斥鎖也是屬于線程之間處理同步互斥方式,有上鎖/解鎖兩種狀態。 互斥鎖函數接口 1)初始化互斥鎖 pthread_mutex_init() man 3 pthread_mutex_init (找不到的情況下首先 sudo apt-get install glibc-doc sudo apt-get install manpages-posix-dev) 動態初始化 int pthread_...

    統計學習方法 - 樸素貝葉斯

    引入問題:一機器在良好狀態生產合格產品幾率是 90%,在故障狀態生產合格產品幾率是 30%,機器良好的概率是 75%。若一日第一件產品是合格品,那么此日機器良好的概率是多少。 貝葉斯模型 生成模型與判別模型 判別模型,即要判斷這個東西到底是哪一類,也就是要求y,那就用給定的x去預測。 生成模型,是要生成一個模型,那就是誰根據什么生成了模型,誰就是類別y,根據的內容就是x 以上述例子,判斷一個生產出...

    styled-components —— React 中的 CSS 最佳實踐

    https://zhuanlan.zhihu.com/p/29344146 Styled-components 是目前 React 樣式方案中最受關注的一種,它既具備了 css-in-js 的模塊化與參數化優點,又完全使用CSS的書寫習慣,不會引起額外的學習成本。本文是 styled-components 作者之一 Max Stoiber 所寫,首先總結了前端組件化樣式中的最佳實踐原則,然后在此基...

    基于TCP/IP的網絡聊天室用Java來實現

    基于TCP/IP的網絡聊天室實現 開發工具:eclipse 開發環境:jdk1.8 發送端 接收端 工具類 運行截圖...

    精品国产乱码久久久久久蜜桃不卡