日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Netty 框架学习(一):初始netty

發布時間:2025/1/21 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Netty 框架学习(一):初始netty 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • 一、Netty簡介
    • 二、開發包獲取
      • maven依賴
    • 三、簡單例子
      • 服務端
      • 客戶端

一、Netty簡介

官方定義為:”Netty 是一款異步的事件驅動的網絡應用程序框架,支持快速地開發可維護的高性能的面向協議的服務器 和客戶端”。
使用Netty不適用jdk原生NIO原因

  • 使用JDK自帶的NIO需要了解太多的概念,編程復雜,一不小心bug橫飛
  • Netty底層IO模型隨意切換,只需要做微小的改動,Netty可以直接從NIO模型變身為IO模型
  • Netty自帶的拆包解包,異常檢測等機制讓你從NIO的繁重細節中脫離出來,只需要關心業務邏輯
  • 解決許多空輪詢查詢bug
  • Netty底層對線程,selector做了很多細小的優化,精心設計的reactor線程模型做到非常高效的并發處理
  • 自帶各種協議棧可以處理任何一種通用協議
  • Netty社區活躍
  • Netty已經歷各大rpc框架,消息中間件,分布式通信中間件線上的廣泛驗證,健壯性無比強大

二、開發包獲取

maven依賴

  • 如果使用 Maven 進行項目開發管理,則 Netty 也提供了 Maven 依賴。
  • 可以直接從Maven倉庫拿到依賴
<!-- https://mvnrepository.com/artifact/io.netty/netty-all --><dependency><groupId>io.netty</groupId><artifactId>netty-all</artifactId><version>4.1.36.Final</version></dependency>
  • 也可以從Netty官網拿依賴
<dependency><groupId>io.netty</groupId><artifactId>netty</artifactId> <!-- 4.0以上版本用netty-all --><version>X.Y.Z.Q</version><scope>compile</scope></dependency>

三、簡單例子

以一個簡單的例子來對 Netty 網絡編程有一個初步的了解,其中的細節可以以后慢慢消化:先開啟服務器等待客戶端連接,然后開啟客戶端,同時給服務器發送一條消息,服務器接收到消息后,回發一條消息。

服務端

  • TimeServer
public class TimeServer {public void bind(int port) {/* *配置服務端的 NIO 線程池,用于網絡事件處理,實質上他們就是 Reactor 線程組bossGroup 用于服務端接受客戶端連接,workerGroup 用于進行 SocketChannel 網絡讀寫*/EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workerGroup = new NioEventLoopGroup();try {/*** ServerBootstrap 是 Netty 用于啟動 NIO 服務端的輔助啟動類,用于降低開發難度*/ServerBootstrap b = new ServerBootstrap();b.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG,1024).childHandler(new ChildChannelHandler());ChannelFuture f = b.bind(port).sync();f.channel().closeFuture().sync();} catch (Exception e) {e.printStackTrace();} finally {/**優雅退出,釋放線程池資源*/bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}/*** @param args* @throws Exception*/public static void main(String[] args) throws Exception {int port = 8080;if (args != null && args.length > 0) {try {port = Integer.valueOf(args[0]);} catch (NumberFormatException e) {// 采用默認值}}new TimeServer().bind(port);} }
  • ChildChannelHandler
public class ChildChannelHandler extends ChannelInitializer<SocketChannel> {protected void initChannel(SocketChannel socketChannel) throws Exception {socketChannel.pipeline().addLast(new TimeServerHandler());} }
  • TimeServerHandler
/*** @author shuliangzhao* @Title: TimeServerHandler* @ProjectName design-parent* @Description: TODO* @date 2019/8/13 21:04*/ public class TimeServerHandler extends ChannelInboundHandlerAdapter {/*** 收到客戶端消息,自動觸發* @param ctx* @param msg* @throws Exception*/@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {//將 msg 轉為 Netty 的 ByteBuf 對象,類似 JDK 中的 java.nio.ByteBuffer,不過 ButeBuf 功能更強,更靈活ByteBuf buf = (ByteBuf) msg;//readableBytes:獲取緩沖區可讀字節數,然后創建字節數組//從而避免了像 java.nio.ByteBuffer 時,只能盲目的創建特定大小的字節數組,比如 1024byte[] req = new byte[buf.readableBytes()];//readBytes:將緩沖區字節數組復制到新建的 byte 數組中//然后將字節數組轉為字符串buf.readBytes(req);String body = new String(req, "UTF-8");System.out.println("The time server receive order : " + body);//回復消息//copiedBuffer:創建一個新的緩沖區,內容為里面的參數//通過 ChannelHandlerContext 的 write 方法將消息異步發送給客戶端*/String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new java.util.Date(System.currentTimeMillis()).toString() : "BAD ORDER";ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());ctx.write(resp);}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {//flush:將消息發送隊列中的消息寫入到 SocketChannel 中發送給對方,為了頻繁的喚醒 Selector 進行消息發送//Netty 的 write 方法并不直接將消息寫如 SocketChannel 中,調用 write 只是把待發送的消息放到發送緩存數組中,再通過調用 flush//方法,將發送緩沖區的消息全部寫入到 SocketChannel 中ctx.flush();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {/**當發生異常時,關閉 ChannelHandlerContext,釋放和它相關聯的句柄等資源 */ctx.close();} }

客戶端

  • TimeClient
/*** @author shuliangzhao* @Title: TimeClient* @ProjectName design-parent* @Description: TODO* @date 2019/8/13 21:13*/ public class TimeClient {public void connect(int port, String host) throws Exception {// 配置客戶端NIO線程組EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap b = new Bootstrap();b.group(group).channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() {@Overridepublic void initChannel(SocketChannel ch)throws Exception {ch.pipeline().addLast(new TimeClientHandler());}});// 發起異步連接操作ChannelFuture f = b.connect(host, port).sync();// 當代客戶端鏈路關閉f.channel().closeFuture().sync();} finally {// 優雅退出,釋放NIO線程組group.shutdownGracefully();}}/*** @param args* @throws Exception*/public static void main(String[] args) throws Exception {int port = 8080;if (args != null && args.length > 0) {try {port = Integer.valueOf(args[0]);} catch (NumberFormatException e) {// 采用默認值}}new TimeClient().connect(port, "127.0.0.1");} }
  • TimeClientHandler
/*** @author shuliangzhao* @Title: TimeClientHandler* @ProjectName design-parent* @Description: TODO* @date 2019/8/13 21:14*/ public class TimeClientHandler extends ChannelInboundHandlerAdapter {private final ByteBuf firstMessage;/*** Creates a client-side handler.*/public TimeClientHandler() {byte[] req = "QUERY TIME ORDER".getBytes();firstMessage = Unpooled.buffer(req.length);firstMessage.writeBytes(req);}/*** 當客戶端和服務端 TCP 鏈路建立成功之后,Netty 的 NIO 線程會調用 channelActive 方法* @param ctx*/@Overridepublic void channelActive(ChannelHandlerContext ctx) {String reqMsg = "我是客戶端 " + Thread.currentThread().getName();System.out.println(reqMsg);//writeBytes:將指定的源數組的數據傳輸到緩沖區//調用 ChannelHandlerContext 的 writeAndFlush 方法將消息發送給服務器ctx.writeAndFlush(firstMessage);}/*** 當服務端返回應答消息時,channelRead 方法被調用,從 Netty 的 ByteBuf 中讀取并打印應答消息* @param ctx* @param msg* @throws Exception*/@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg)throws Exception {ByteBuf buf = (ByteBuf) msg;byte[] req = new byte[buf.readableBytes()];buf.readBytes(req);String body = new String(req, "UTF-8");System.out.println("Now is : " + body);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {// 釋放資源System.out.println("Unexpected exception from downstream : "+ cause.getMessage());ctx.close();} }

基于 Netty 的應用開發不但 API 使用簡單,開發模式固定,而且擴展性和定制性非常好。需要注意的是,本示例沒有考慮讀半包的處理,對于簡單的功能,或者不苛責的環境下是沒有的問題的,但是如果進行性能測試或者壓力測試,就不敢保證正常運行了,所以后面會介紹半包處理情況。

總結

以上是生活随笔為你收集整理的Netty 框架学习(一):初始netty的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。