成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

玩轉(zhuǎn)Netty,從“Hello World”開始!

網(wǎng)絡(luò) 網(wǎng)絡(luò)管理
如果在項目的開發(fā)中,要實現(xiàn)穩(wěn)定的網(wǎng)絡(luò)通信,就得考慮網(wǎng)絡(luò)的閃斷、客戶端的重復接入、客戶端的安全認證、消息的編解碼、半包讀寫……

大家好,我是老三,之前里,我們討論了Java的三種IO模型,提到了網(wǎng)絡(luò)通信框架Netty,它簡化和優(yōu)化了NIO的使用,這期,我們正式開始走近Netty。

為什么要用Netty?

首先當然是NIO的使用,本身比較復雜,而且還存在一些問題。

除此之外,如果在項目的開發(fā)中,要實現(xiàn)穩(wěn)定的網(wǎng)絡(luò)通信,就得考慮網(wǎng)絡(luò)的閃斷、客戶端的重復接入、客戶端的安全認證、消息的編解碼、半包讀寫……

所以,巧了,恰好有這么一個成熟穩(wěn)定、性能強大、開箱即用的網(wǎng)絡(luò)框架擺在我們面前,相比較Java NIO,Netty更加出色:

  • 易用性: Netty 在 NIO 基礎(chǔ)上進行了更高層次的封裝,屏蔽了 NIO 的復雜性,大大降低了開發(fā)難度;Netty 提供了很多開箱即用的工具,例如常用的行解碼器、長度域解碼器等,不需要自己再實現(xiàn)。
  • 穩(wěn)定性: Netty 更加可靠穩(wěn)定,修復和完善了 JDK NIO 較多已知問題,例如臭名昭著的 select 空轉(zhuǎn)導致 CPU 消耗 100%,TCP 斷線重連,keep-alive 檢測等問題。
  • 可擴展性: Netty 的的可擴展性做的非常好,比如支持可定制化的線程模型。

我們有什么理由拒絕這么一款優(yōu)秀的網(wǎng)絡(luò)通信框架呢?代碼怎么寫不是寫嘍!

初識Netty

什么是Netty?

Netty官方是這么定義Netty的:

Netty 是一個異步事件驅(qū)動的網(wǎng)絡(luò)應用程序框架,用于快速開發(fā)可維護的高性能協(xié)議服務器和客戶端。

圖片

組成圖-來源官方

  • Netty是一個開源的、單線程模型的 Java 網(wǎng)絡(luò)編程框架。
  • Netty基于 NIO ,被廣泛應用于各種網(wǎng)絡(luò)應用程序開發(fā)。
  • Netty支持多種協(xié)議,包括但不限于 HTTP、WebSocket、TCP、UDP 和 SSL/TLS 協(xié)議等。
  • Netty 是非阻塞的,事件驅(qū)動的框架。
  • Netty具有高性能、可擴展和易于使用的優(yōu)點。

Netty的現(xiàn)狀?

Netty 由 JBoss 社區(qū)開發(fā)維護的,它的社區(qū)相對比較活躍:

  • https://github.com/netty/netty:Github已經(jīng)收獲31.2K星標
  • https://netty.io/:官方網(wǎng)站,提供了比較完整的文檔

官方目前最新的版本是5.x,,但是很不幸,已經(jīng)被社區(qū)放棄開發(fā)維護,屬于廢棄版本,最新的穩(wěn)定版本是4.x 。

一般使用,推薦4.x,Netty 4.x對3.x不做兼容,我們后續(xù)的學習也基于Netty 4.x版本。

誰在用Netty?

作為最流行的網(wǎng)絡(luò)通信框架,大量的公司選擇它作為底層網(wǎng)絡(luò)通信框架,包括不限于:

圖片

使用Netty的公司

我們可能自己沒有直接用過Netty,但其實熟悉的很多開源中間件,都用到了Netty,比如:

  • 服務治理:Apache Dubbo、gRPC。
  • 大數(shù)據(jù):Hbase、Spark、Flink、Storm。
  • 搜索引擎:Elasticsearch。
  • 消息隊列:RocketMQ、ActiveMQ。

用到Netty的優(yōu)秀產(chǎn)品非常多,大家感興趣可以看看:https://netty.io/wiki/related-projects.html。

從"Hello World"開始

氣氛襯托到這,不寫個Demo也過不去,還是從"Hello World"開始,我們領(lǐng)略一下Netty的風采。

  1. 創(chuàng)建一個Maven項目:這個就不用多說了吧

圖片

創(chuàng)建Maven項目

  1. 導入依賴:我們直接用4.x最新的版本
<dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1.92.Final</version>
        </dependency>
  1. 編寫代碼:那么我們就開始編寫這個Demo的服務器和客戶端相關(guān)代碼
  • NettyServer:基于Netty的客戶端
/**
 * <p>Date: 2023/5/14 10:29</p>
 * <p>Author: fighter3</p>
 * <p>Description: Netty服務端Demo</p>
 */
public class NettyServer{
    // 服務器監(jiān)聽的端口號
    private int port;

    public NettyServer(int port) {
        this.port = port;
    }

    /**
     * 啟動Netty服務器
     * @throws InterruptedException
     */
    public void run() throws InterruptedException {
        // 創(chuàng)建boss線程組和worker線程組
        // bossGroup 用于監(jiān)聽客戶端的連接請求,將連接請求發(fā)送給 workerGroup 進行處理
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        // workerGroup 用于處理客戶端連接的數(shù)據(jù)讀寫
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            // 創(chuàng)建 ServerBootstrap 對象,用于啟動 Netty 服務器
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            // 綁定線程池事件組
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    // 通道初始化回調(diào)函數(shù),在啟動的時候可以自動調(diào)用
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            // 添加消息處理器
                            pipeline.addLast(new NettyServerHandler());
                        }
                    });

            // 綁定端口,開始接收客戶端請求
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

            System.out.println("Netty服務器監(jiān)聽端口:"+port);

            // 等待服務端監(jiān)聽端口關(guān)閉
            channelFuture.channel().closeFuture().sync();
        } finally {
            //釋放線程組資源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 創(chuàng)建服務器對象,監(jiān)聽端口號為 8888
        NettyServer server = new NettyServer(8888);
        System.out.println("============Netty服務器啟動...=============");
        // 啟動服務器
        server.run();
        System.out.println("============Netty服務器停止...=============");
    }
}
  • NettyServerHandler:服務器的消息處理器,用于處理各種事件
/**
 * <p>Date: 2023/5/14 10:30</p>
 * <p>Author: fighter3</p>
 * <p>Description: Netty服務器消息處理器</p>
 */
public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 當客戶端上線的時候會觸發(fā)這個方法
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String message="你好,靚仔!";
        ByteBuf hello = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
        // 發(fā)送消息
        ctx.writeAndFlush(hello);
    }

    /**
     *當 Channel 中有來自客戶端的數(shù)據(jù)時就會觸發(fā)這個方法
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("客戶端發(fā)來的消息:" + buf.toString(CharsetUtil.UTF_8)); // 接收消息并打印輸出
    }

    /**
     * 當有異常時觸發(fā)這個方法
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
  • NettyClient:使用Netty的客戶端,通過ip和端口連接服務端
/**
 * <p>Date: 2023/5/14 10:32</p>
 * <p>Author: fighter3</p>
 * <p>Description: Netty客戶端Demo</p>
 */
public class NettyClient {
    // 服務器 IP
    private String host;
    // 服務器監(jiān)聽的端口號
    private int port;

    public NettyClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    /**
     * 啟動 Netty 客戶端
     */
    public void run() throws InterruptedException {
        // 創(chuàng)建事件循環(huán)組
        NioEventLoopGroup group = new NioEventLoopGroup();
        try {
            // 創(chuàng)建 Bootstrap 對象
            Bootstrap bootstrap = new Bootstrap();
            // 配置 Bootstrap 對象
            // 設(shè)置線程組
            bootstrap.group(group)
                    // 設(shè)置客戶端通信的通道類型為NIO類型
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        // 通道初始化回調(diào)函數(shù),在啟動的時候可以自動調(diào)用
                        @Override
                        public void initChannel(SocketChannel ch) throws Exception {
                            // 添加消息處理器
                            ch.pipeline().addLast(new NettyClientHandler());
                        }
                    });
            // 連接服務器,異步等待連接成功
            ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
            System.out.println("===========Netty客戶端連接服務端=========");

            // 等待客戶端連接關(guān)閉
            channelFuture.channel().closeFuture().sync();
        } finally {
            //釋放資源
            group.shutdownGracefully();
        }
    }

    public static void main(String[] args) throws InterruptedException {
       // 創(chuàng)建客戶端對象,并連接到服務器
        NettyClient client = new NettyClient("127.0.0.1", 8888);
        // 啟動客戶端,開始發(fā)送消息
        client.run();
    }
}
  • NettyClientHandler:Netty客戶端處理器,用于處各種事件
/**
 * <p>Date: 2023/5/14 10:33</p>
 * <p>Author: fighter3</p>
 * <p>Description: Netty客戶端處理器</p>
 */
public class NettyClientHandler extends ChannelInboundHandlerAdapter {

    /**
     * 當 Channel 準備就緒時就會觸發(fā)這個方法
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        String message="大佬,帶帶我!";
        ByteBuf hello = Unpooled.copiedBuffer(message, CharsetUtil.UTF_8);
        // 發(fā)送消息
        ctx.writeAndFlush(hello);
    }

    /**
     * 當 Channel 中有來自服務器的數(shù)據(jù)時就會觸發(fā)這個方法
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf = (ByteBuf) msg;
        System.out.println("服務端發(fā)來的消息:" + buf.toString(CharsetUtil.UTF_8)); // 接收消息并打印輸出
    }

    /**
     * 發(fā)生異常就會觸發(fā)這個方法
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        ctx.close();
    }
}
  1. 運行一下:先啟動NettyServer,再啟動NettyClient,看下運行結(jié)果
============Netty服務器啟動...=============
Netty服務器監(jiān)聽端口:8888
客戶端發(fā)來的消息:大佬,帶帶我!
===========Netty客戶端連接服務端=========
服務端發(fā)來的消息:你好,靚仔!

好了,一個簡單的Netty入門Demo就寫完了,Netty是一個雙工通信的網(wǎng)絡(luò)框架,可以看到,服務端和客戶端,流程基本上一致,主要包括這么幾個步驟:

  1. 創(chuàng)建事件循環(huán)組和相關(guān)對象,用于監(jiān)聽和處理網(wǎng)絡(luò)事件;
  2. 配置 Netty 服務器或客戶端的啟動參數(shù),包括線程組、通道類型、TCP 參數(shù)等;
  3. 給服務器或客戶端的 ChannelPipeline 添加各種 ChannelHandler,用于處理不同的網(wǎng)絡(luò)事件;
  4. 綁定端口啟動服務器或連接服務器;
  5. 等待服務器或客戶端連接關(guān)閉,釋放相關(guān)資源。

圖片

服務器&客戶端初始化啟動流程

雖然這個Demo比較簡單,但其實已經(jīng)用到了Netty里幾個比較關(guān)鍵的組件:

  1. ByteBuf:Netty 的字節(jié)容器,類似于 Java 的 ByteBuffer,但是提供了更加強大、簡便且安全的 API,用于在網(wǎng)絡(luò)中傳遞二進制數(shù)據(jù);
  2. EventLoopGroup:Netty 的事件循環(huán)組,用于管理和調(diào)度連接到服務器或者從服務器連接出去的所有 Channel 上的事件循環(huán);
  3. ServerBootstrap:Netty 的服務器啟動類,用于啟動和配置一個 TCP/IP 服務器;
  4. Bootstrap:Netty 的客戶端啟動類,用于啟動和配置一個 TCP/IP 客戶端;
  5. Channel:Netty 的核心概念,用于表示一個通信通道,可以讀取和寫入數(shù)據(jù);
  6. ChannelPipeline:Netty 的 Channel 處理器,用于在傳入的數(shù)據(jù)上執(zhí)行一組 ChannelHandler;
  7. ChannelHandler:Netty 的核心組件,用于處理各種通信事件,例如讀取數(shù)據(jù)、寫數(shù)據(jù)、建立連接等;

圖片

Netty的重要組件

后續(xù),我們還會和這些組件打更多的交道。

好了,那么這期內(nèi)容就到這了,這期里我們初步了解了Netty,包括什么是Netty、Netty現(xiàn)狀、Netty的應用,還寫了一個簡單的Demo。下一期,我們繼續(xù)深入了解Netty,敬請期待。

參考:

[1].https://netty.io/

[2].《Netty權(quán)威指南》

[3]. 《Netty核心原理剖析與RPC實踐》

責任編輯:武曉燕 來源: 三分惡
相關(guān)推薦

2021-01-20 07:48:28

TechFlow前端網(wǎng)站

2019-07-30 14:35:58

TCPIP模型

2012-03-06 10:22:00

程序

2016-12-14 14:41:20

Hello World程序運行機制

2016-12-13 14:12:25

程序機制

2014-12-19 10:07:10

C

2017-11-23 17:45:46

Yii框架IntelYii框架深度剖析

2011-03-21 09:45:52

Hello WorldObjective-C生命周期

2009-07-30 13:21:17

Scala入門Hello World

2023-01-06 08:18:44

2009-08-11 10:32:23

什么是Groovy

2023-09-04 07:30:03

Wasm匯編語言

2009-09-16 17:15:19

OSGi Bundle

2011-06-08 14:39:06

Qt 教程

2024-03-13 13:53:10

C++程序開發(fā)

2012-04-25 10:07:26

Windows Pho

2012-02-20 14:26:48

JavaPlay Framew

2021-06-16 14:18:37

NettyReactor線程模型

2009-08-14 16:54:19

C# Hello Wo

2021-11-26 08:22:01

Java動態(tài)開發(fā)
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 中文在线a在线 | 亚洲欧美一区二区三区在线 | 日韩在线精品 | 国产视频亚洲视频 | 国产成人aⅴ | 国产精品99久久久久久宅男 | 亚洲国产网| 欧一区二区 | 99热播精品| 日本成人在线免费视频 | 欧美1区| 巨大荫蒂视频欧美另类大 | 国产美女精品视频 | 成人国产精品色哟哟 | 日韩欧美专区 | 一区二区三区四区在线视频 | 夜夜爽99久久国产综合精品女不卡 | 视频一区在线播放 | 日韩一区二区三区在线播放 | 国产精品2 | 国产成人免费视频 | 亚洲欧美激情精品一区二区 | 国产一级片av | 欧美特级黄色 | 国产精品久久久久久久久免费樱桃 | 天天干夜夜操 | 久久久久国产精品午夜一区 | av国产精品 | 欧美成年人网站 | 中文字幕一区二区三区在线观看 | 国产一区二区三区在线 | 日韩午夜网站 | 免费看国产精品视频 | 青青草中文字幕 | 国产福利在线 | 日韩在线观看一区二区三区 | 久久久国产网站 | 激情三区 | 午夜a区| 欧美视频免费在线观看 | 国产高清视频一区 |