Java網絡編程 — Netty入門

認識Netty

Netty簡介

Netty is?an asynchronous event-driven network application framework?for rapid development of maintainable high performance protocol servers & clients.

Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server.

Netty是一個異步事件驅動的網絡應用框架,用于快速開發可維護的高性能協議服務器和客戶端。

Netty是一款NIO客戶端服務器框架,可以快速輕松地開發協議服務器和客戶端等網絡應用程序。它極大地簡化并簡化了TCP和UDP套接字服務器等網絡編程。

Netty架構圖如下圖所示

Netty的特性總結如下表

為什么選擇Netty

Netty是業界最流行的NIO框架之一,它的健壯性、功能、性能、可定制性和可擴展性在同類框架中都是首屈一指的,已經得到成百上千的商用項目驗證。通過對Netty的分析,將它的優點總結如下:

  • API使用簡單,開發門檻低;
  • 功能強大,預置了多種編解碼功能,支持多種主流協議;
  • 定制能力強,可以通過ChannelHandler對通信框架進行靈活地擴展;
  • 性能高,通過與其他業界主流的NIO框架對比,Netty的綜合性能最優;
  • 成熟、穩定,Netty修復了已經發現的所有JDK NIO BUG,業務開發人員不需要再為NIO的BUG而煩惱;
  • 社區活躍,版本迭代周期短,發現的BUG可以被及時修復,同時,更多的新功能會加入;
  • 經歷了大規模的商業應用考驗,質量得到驗證。

核心概念

Netty is a non-blocking framework. This leads to high throughput compared to blocking IO.?Understanding non-blocking IO is crucial to understanding Netty’s core components and their relationships.

Channel

Channel?is the base of Java NIO. It represents an open connection which is capable of IO operations such as reading and writing.

Channel是Java NIO的基礎。它表示一個開放的連接,能夠進行IO操作,例如讀寫。

Future

Netty中的每個IO操作都是非阻塞的,這意味著每次操作都會在通話結束后立即返回。

標準Java庫中有一個Future接口,但對Netty而言不方便 - 我們只能向Future詢問完成操作或阻止當前線程,直到完成操作。這就是為什么Netty有自己的ChannelFuture接口,我們可以將回調傳遞給ChannelFuture,其將在操作完成時被調用

Events and Handlers

Netty使用事件驅動的應用程序范例,因此數據處理的管道是通過處理程序的一系列事件。事件和處理程序可以與入站(inbound)和出站(outbound)數據流相關聯。?Inbound events(入站事件)可以如下所示:

  • Channel activation and deactivation
  • Read operation events
  • Exception events
  • User events

Outbound events(出站事件)更簡單,通常與打開/關閉連接(?opening/closing a connection)和寫入/清空數據(writing/flushing data)有關。

Netty應用程序由幾個網絡和應用程序邏輯事件及其處理程序組成。通道事件處理程序的基礎接口是ChannelHandler及其子接口ChannelOutboundHandler``ChannelInboundHandler

Netty提供了大量ChannelHandler實現的類。值得注意的是適配器只是空的實現,例如ChannelInboundHandlerAdapterChannelOutboundHandlerAdapter

Encoders and Decoders

當我們使用網絡協議時,我們需要執行數據序列化和反序列化。為此,Netty為了能夠解碼傳入數據引入了ChannelInboundHandler的擴展解碼器,大多數解碼器的基類ByteToMessageDecoder。對于編碼輸出數據,Netty同樣提供了ChannelOutboundHandler的擴展編碼器, MessageToByteEncoder是大多數編碼器實現的基礎。

應用示例

Server Application

創建一個簡單協議服務器的項目,它接收請求,執行計算并發送響應。

Dependencies

<dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.10.Final</version>
</dependency>
復制代碼

Data Model

public class RequestData {private int intValue;private String stringValue;// standard getters and setters
}
復制代碼
public class ResponseData {private int intValue;// standard getters and setters
}
復制代碼

Request Decoder

It should be noted that Netty works with socket receive buffer, which is represented not as a queue but just as a bunch of bytes. This means that our inbound handler can be called when the full message is not received by a server.

We must make sure that we have received the full message before processing. The decoder for RequestData is shown next:

public class RequestDecoder extends ReplayingDecoder<RequestData> {private final Charset charset = Charset.forName("UTF-8");@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {RequestData data = new RequestData();data.setIntValue(in.readInt());int strLen = in.readInt();data.setStringValue(in.readCharSequence(strLen, charset).toString());out.add(data);}
}
復制代碼

ReplayingDecoder It uses an implementation of ByteBuf which throws an exception when there is not enough data in the buffer for the reading operation.

When the exception is caught the buffer is rewound to the beginning and the decoder waits for a new portion of data. Decoding stops when the out list is not empty after decode execution.

Response Encoder

public class ResponseDataEncoder extends MessageToByteEncoder<ResponseData> {@Overrideprotected void encode(ChannelHandlerContext ctx, ResponseData msg, ByteBuf out) throws Exception {out.writeInt(msg.getIntValue());}
}
復制代碼

Request Processing

public class ProcessingHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {RequestData requestData = (RequestData) msg;ResponseData responseData = new ResponseData();responseData.setIntValue(requestData.getIntValue() * 2);ChannelFuture future = ctx.writeAndFlush(responseData);future.addListener(ChannelFutureListener.CLOSE);System.out.println(requestData);}
}
復制代碼

Server Bootstrap

public class NettyServer {private int port;// constructorpublic static void main(String[] args) throws Exception {int port = args.length > 0? Integer.parseInt(args[0]);: 8080;new NettyServer(port).run();}public void run() throws Exception {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new RequestDecoder(), new ResponseDataEncoder(), new ProcessingHandler());}}).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true);ChannelFuture f = b.bind(port).sync();f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();bossGroup.shutdownGracefully();}}
}
復制代碼

Client Application

The client should perform reverse encoding and decoding, so we need to have a?RequestDataEncoder?and?ResponseDataDecoder:

public class RequestDataEncoder extends MessageToByteEncoder<RequestData> {private final Charset charset = Charset.forName("UTF-8");@Overrideprotected void encode(ChannelHandlerContext ctx, RequestData msg, ByteBuf out) throws Exception {out.writeInt(msg.getIntValue());out.writeInt(msg.getStringValue().length());out.writeCharSequence(msg.getStringValue(), charset);}
}
復制代碼
public class ResponseDataDecoder extends ReplayingDecoder<ResponseData> {@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {ResponseData data = new ResponseData();data.setIntValue(in.readInt());out.add(data);}
}
復制代碼

Also, we need to define a?ClientHandler?which will send the request and receive the response from server:

public class ClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {RequestData msg = new RequestData();msg.setIntValue(123);msg.setStringValue("all work and no play makes jack a dull boy");ChannelFuture future = ctx.writeAndFlush(msg);}@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {System.out.println((ResponseData)msg);ctx.close();}
}
復制代碼

Now let’s bootstrap the client:

public class NettyClient {public static void main(String[] args) throws Exception {String host = "localhost";int port = 8080;EventLoopGroup workerGroup = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(workerGroup);b.channel(NioSocketChannel.class);b.option(ChannelOption.SO_KEEPALIVE, true);b.handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch) throws Exception {ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(), new ClientHandler());}});ChannelFuture f = b.connect(host, port).sync();f.channel().closeFuture().sync();} finally {workerGroup.shutdownGracefully();}}
}
復制代碼

Now we can run the client’s main method and take a look at the console output. As expected, we got ResponseData with intValue equal to 246.

參考資源

  • Netty權威指南(第2版)-李林鋒

  • Introduction to Netty

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390209.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390209.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390209.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

har文件分析http_如何使用HAR文件分析一段時間內的性能

har文件分析httpWhen I consider the performance of a website, several things come to mind. I think about looking at the requests of a page, understanding what resources are being loaded, and how long these resources take to be available to users.當我考慮網站…

第一階段:前端開發_Mysql——表與表之間的關系

2018-06-26 表與表之間的關系 一、一對多關系&#xff1a; 常見實例&#xff1a;分類和商品&#xff0c;部門和員工一對多建表原則&#xff1a;在從表&#xff08;多方&#xff09;創建一個字段&#xff0c;字段作為外鍵指向主表&#xff08;一方&#xff09;的一方      …

按鈕提交在url后添加字段_在輸入字段上定向單擊“清除”按鈕(X)

按鈕提交在url后添加字段jQuery makes it easy to get your project up and running. Though its fallen out of favor in recent years, its still worth learning the basics, especially if you want quick access to its powerful methods.jQuery使您可以輕松啟動和運行項目…

429. N 叉樹的層序遍歷

429. N 叉樹的層序遍歷 給定一個 N 叉樹&#xff0c;返回其節點值的層序遍歷。&#xff08;即從左到右&#xff0c;逐層遍歷&#xff09;。 樹的序列化輸入是用層序遍歷&#xff0c;每組子節點都由 null 值分隔&#xff08;參見示例&#xff09;。 - 示例 1&#xff1a;輸入…

javascript如何阻止事件冒泡和默認行為

阻止冒泡&#xff1a; 冒泡簡單的舉例來說&#xff0c;兒子知道了一個秘密消息&#xff0c;它告訴了爸爸&#xff0c;爸爸知道了又告訴了爺爺&#xff0c;一級級傳遞從而以引起事件的混亂&#xff0c;而阻止冒泡就是不讓兒子告訴爸爸&#xff0c;爸爸自然不會告訴爺爺。下面的d…

89. Gray Code - LeetCode

為什么80%的碼農都做不了架構師&#xff1f;>>> Question 89. Gray Code Solution 思路&#xff1a; n 0 0 n 1 0 1 n 2 00 01 10 11 n 3 000 001 010 011 100 101 110 111 Java實現&#xff1a; public List<Integer> grayCode(int n) {List&…

400. 第 N 位數字

400. 第 N 位數字 在無限的整數序列 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, …中找到第 n 位數字。 注意&#xff1a;n 是正數且在 32 位整數范圍內&#xff08;n < 231&#xff09;。 示例 1&#xff1a; 輸入&#xff1a;3 輸出&#xff1a;3 示例 2&#xff1a; 輸入&…

1.初識Linux

1.Linux 區分大小寫 2.shell命令行-bash 進入終端->[stulocalhost~]$ (其中,Stu為登錄用戶名&#xff0c;localhost為登錄主機名&#xff0c;’~’ 表示當前用戶正處在stu用戶的家目錄中, 普通用戶的提示符以$結尾&#xff0c;而根用戶以’#’結尾) 3.Linux中所謂的命令(…

這份NLP研究進展匯總請收好,GitHub連續3天最火的都是它

最近&#xff0c;有一份自然語言處理 (NLP) 進展合輯&#xff0c;一發布就受到了同性交友網站用戶的瘋狂標星&#xff0c;已經連續3天高居GitHub熱門榜首位。 合集里面包括&#xff0c;20多種NLP任務前赴后繼的研究成果&#xff0c;以及用到的數據集。 這是來自愛爾蘭的Sebasti…

基于模型的嵌入式開發流程_如何使用基于模型的測試來改善工作流程

基于模型的嵌入式開發流程Unit testing is not enough – so lets start using model-based testing to improve our workflows.單元測試還不夠–因此&#xff0c;讓我們開始使用基于模型的測試來改善我們的工作流程。 Software testing is an important phase in building a …

166. 分數到小數

166. 分數到小數 給定兩個整數&#xff0c;分別表示分數的分子 numerator 和分母 denominator&#xff0c;以 字符串形式返回小數 。 如果小數部分為循環小數&#xff0c;則將循環的部分括在括號內。 如果存在多個答案&#xff0c;只需返回 任意一個 。 對于所有給定的輸入…

最近用.NET實現DHT爬蟲,全.NET實現

最近用.NET實現DHT爬蟲&#xff0c;全.NET實現&#xff0c;大家可以加我QQ交流下 309159808 轉載于:https://www.cnblogs.com/oshoh/p/9236186.html

C++貪吃蛇

動畫鏈接 GitHub鏈接&#xff1a;https://github.com/yanpeng1314/Snake 1 #include "Snake.h"2 3 int iScore 0;4 int iGrade 1;5 6 //蛇頭蛇尾初始位置7 int x_head 1, y_head 3;8 int x_tail 1, y_tail 1;9 10 //地圖坐標11 int i_Map 1, j_Map 1;12 13 /…

遠程辦公招聘_招聘遠程人才時要尋找的5種技能

遠程辦公招聘Remote work is a fast emerging segment of the labor market. How to embrace this shift as an employer - and find, recruit, and empower remote staff - is a question many companies and hiring managers are grappling with.遠程工作是勞動力市場中快速崛…

10分鐘騰訊云配置免費https

騰訊云免費證書申請地址&#xff1a; https://console.cloud.tencent... 填寫相關信息 域名身份驗證 文件驗證 將fileauth.text 創建在網站訪問根目錄的 .well-known/pki-validation/目錄使得 www.**.com/.well-known/pki-validation/fileauth.text 能夠訪問詳情 等待5分鐘左右…

1588. 所有奇數長度子數組的和

1588. 所有奇數長度子數組的和 給你一個正整數數組 arr &#xff0c;請你計算所有可能的奇數長度子數組的和。 子數組 定義為原數組中的一個連續子序列。 請你返回 arr 中 所有奇數長度子數組的和 。 示例 1&#xff1a; 輸入&#xff1a;arr [1,4,2,5,3] 輸出&#xff1…

洛谷P3195 [HNOI2008]玩具裝箱TOY(單調隊列優化DP)

題目描述 P教授要去看奧運&#xff0c;但是他舍不下他的玩具&#xff0c;于是他決定把所有的玩具運到北京。他使用自己的壓縮器進行壓縮&#xff0c;其可以將任意物品變成一堆&#xff0c;再放到一種特殊的一維容器中。P教授有編號為1...N的N件玩具&#xff0c;第i件玩具經過壓…

680. 驗證回文字符串 Ⅱ

680. 驗證回文字符串 Ⅱ 給定一個非空字符串 s&#xff0c;最多刪除一個字符。判斷是否能成為回文字符串。 示例 1: 輸入: s “aba” 輸出: true 示例 2: 輸入: s “abca” 輸出: true 解釋: 你可以刪除c字符。 示例 3: 輸入: s “abc” 輸出: false 解題思路 使用…

Android--RxJava2更新體驗

截止日前最新版2017-3-15: RxJava compile ‘io.reactivex:rxjava:1.2.7’ compile ‘io.reactivex:rxandroid:1.2.1’ RxJava2 compile “io.reactivex.rxjava2:rxjava:2.0.7” compile “io.reactivex.rxjava2:rxandroid:2.0.1” 1:create操作改變 Rxjava CompositeSubscri…

kotlin和java語言_Kotlin VS Java – 2020年您應該學習哪種編程語言?

kotlin和java語言It has been several years since Kotlin came out, and it has been doing well. Since it was created specifically to replace Java, Kotlin has naturally been compared with Java in many respects.自Kotlin問世以來已經有好幾年了&#xff0c;而且一切…