<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Netty 簡易實(shí)戰(zhàn),傻瓜都能看懂!

          共 11658字,需瀏覽 24分鐘

           ·

          2021-07-04 10:48

          點(diǎn)擊關(guān)注公眾號,Java干貨及時送達(dá)

          作者:rickiyang
          出處:www.cnblogs.com/rickiyang/p/11074237.html

          這一節(jié)我們來講解Netty,使用Netty之前我們先了解一下Netty能做什么,無為而學(xué),豈不是白費(fèi)力氣!

          1.使用Netty能夠做什么

          1. 開發(fā)異步、非阻塞的TCP網(wǎng)絡(luò)應(yīng)用程序;
          2. 開發(fā)異步、非阻塞的UDP網(wǎng)絡(luò)應(yīng)用程序;
          3. 開發(fā)異步文件傳輸應(yīng)用程序;
          4. 開發(fā)異步HTTP服務(wù)端和客戶端應(yīng)用程序;
          5. 提供對多種編解碼框架的集成,包括谷歌的Protobuf、Jboss marshalling、Java序列化、壓縮編解碼、XML解碼、字符串編解碼等,這些編解碼框架可以被用戶直接使用;
          6. 提供形式多樣的編解碼基礎(chǔ)類庫,可以非常方便的實(shí)現(xiàn)私有協(xié)議棧編解碼框架的二次定制和開發(fā);
          7. 基于職責(zé)鏈模式的Pipeline-Handler機(jī)制,用戶可以非常方便的對網(wǎng)絡(luò)事件進(jìn)行攔截和定制;
          8. 所有的IO操作都是異步的,用戶可以通過Future-Listener機(jī)制主動Get結(jié)果或者由IO線程操作完成之后主動Notify結(jié)果,用戶的業(yè)務(wù)線程不需要同步等待;
          9. IP黑白名單控制;
          10. 打印消息碼流;
          11. 流量控制和整形;
          12. 性能統(tǒng)計(jì);
          13. 基于鏈路空閑事件檢測的心跳檢測

          2. Netty常用類講解

          在這里我們就一些我們常用到的類做大致的講解,然后再寫入門程序的時候大致知道每一行都講了什么。

          EventLoop,EventLoopGroup

          EventLoop目的是為Channel處理IO操作,一個EventLoop可以為多個Channel服務(wù),EventLoopGroup會包含多個EventLoop。

          BootStrap,ServerBootstrap

          一個Netty應(yīng)用通常由一個Bootstrap開始,它主要作用是配置整個Netty程序,串聯(lián)起各個組件。分享:Spring Boot 學(xué)習(xí)筆記

          ChannelInitializer

          當(dāng)一個鏈接建立時,我們需要知道怎么來接收或者發(fā)送數(shù)據(jù),當(dāng)然,我們有各種各樣的Handler實(shí)現(xiàn)來處理它,那么ChannelInitializer便是用來配置這些Handler,它會提供一個ChannelPipeline,并把Handler加入到ChannelPipeline。

          Handler

          為了支持各種協(xié)議和處理數(shù)據(jù)的方式,便誕生了Handler組件。Handler主要用來處理各種事件,這里的事件很廣泛,比如可以是連接、數(shù)據(jù)接收、異常、數(shù)據(jù)轉(zhuǎn)換等。

          ChannelInboundHandler

          一個最常用的Handler。這個Handler的作用就是處理接收到數(shù)據(jù)時的事件,也就是說,我們的業(yè)務(wù)邏輯一般就是寫在這個Handler里面的,ChannelInboundHandler就是用來處理我們的核心業(yè)務(wù)邏輯。

          Future

          在Netty中所有的IO操作都是異步的,因此,你不能立刻得知消息是否被正確處理,但是我們可以過一會等它執(zhí)行完成或者直接注冊一個監(jiān)聽,具體的實(shí)現(xiàn)就是通過Future和ChannelFutures,他們可以注冊一個監(jiān)聽,當(dāng)操作執(zhí)行成功或失敗時監(jiān)聽會自動觸發(fā)。總之,所有的操作都會返回一個ChannelFuture。

          3. 第一個Helloworld

          上面我們已經(jīng)對常用類進(jìn)行說明,下面我們就使用這些類來構(gòu)建我們的第一個入門程序,本示例我使用的是maven來構(gòu)建工程,如果你使用的是普通的項(xiàng)目則跳過第一步。另外,微信搜索Java技術(shù)棧,在后臺回復(fù):Maven,獲取系列 Maven 教程。

          首先引入maven jar包:

          <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.5.Final</version>
          </dependency>

          下面我們來寫客戶端:

          public class HelloWorldClient {
              private  int port;
              private  String address;

              public HelloWorldClient(int port,String address) {
                  this.port = port;
                  this.address = address;
              }

              public void start(){
                  EventLoopGroup group = new NioEventLoopGroup();

                  Bootstrap bootstrap = new Bootstrap();
                  bootstrap.group(group)
                          .channel(NioSocketChannel.class)
                          .handler(new ClientChannelInitializer());

                  try {
                      Channel channel = bootstrap.connect(address,port).sync().channel();
                      BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
                      for(;;){
                          String msg = reader.readLine();
                          if(msg == null){
                              continue;
                          }             
                          channel.writeAndFlush(msg + "\r\n");
                      }         
                  } catch (Exception e) {
                      e.printStackTrace();
                  }finally {
                      group.shutdownGracefully();
                  }

              }

              public static void main(String[] args) {
                  HelloWorldClient client = new HelloWorldClient(7788,"127.0.0.1");
                  client.start();
              }
          }

          ChannelInitializer用來配置處理數(shù)據(jù)的handler:

          public class ClientChannelInitializer extends  ChannelInitializer<SocketChannel> {

              protected void initChannel(SocketChannel socketChannel) throws Exception {
                  ChannelPipeline pipeline = socketChannel.pipeline();

                  /*
                   * 這個地方的 必須和服務(wù)端對應(yīng)上。否則無法正常解碼和編碼
                   *
                   * 解碼和編碼 我將會在下一節(jié)為大家詳細(xì)的講解。暫時不做詳細(xì)的描述
                   *
                   * /        
                  pipeline.addLast("decoder", new StringDecoder());
                  pipeline.addLast("encoder", new StringEncoder());

                  // 我們自己的handler
                  pipeline.addLast("handler", new HelloWorldClientHandler());
              }
          }

          寫一個我們自己的handler,用自己的方式來處理數(shù)據(jù):

          public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter {
              @Override
              public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                  System.out.println("server say : "+msg.toString());
              }

              @Override
              public void channelActive(ChannelHandlerContext ctx) throws Exception {
                  System.out.println("Client is active");
              }

              @Override
              public void channelInactive(ChannelHandlerContext ctx) throws Exception {
                  System.out.println("Client is close");
              }
          }

          客戶端我們寫完了,下面開始寫服務(wù)器端:

          public class HelloWordServer {
              private int port;

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

              public void start(){
                  EventLoopGroup bossGroup = new NioEventLoopGroup();
                  EventLoopGroup workGroup = new NioEventLoopGroup();

                  ServerBootstrap server = new ServerBootstrap().group(bossGroup,workGroup)
                                              .channel(NioServerSocketChannel.class)
                                              .childHandler(new ServerChannelInitializer());

                  try {
                      ChannelFuture future = server.bind(port).sync();
                      future.channel().closeFuture().sync();
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }finally {
                      bossGroup.shutdownGracefully();
                      workGroup.shutdownGracefully();
                  }
              }

              public static void main(String[] args) {
                  HelloWordServer server = new HelloWordServer(7788);
                  server.start();
              }
          }

          服務(wù)端的ChannelInitializer:

          public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
              @Override
              protected void initChannel(SocketChannel socketChannel) throws Exception {
                  ChannelPipeline pipeline = socketChannel.pipeline();      

                  // 字符串解碼 和 編碼
                  pipeline.addLast("decoder", new StringDecoder());
                  pipeline.addLast("encoder", new StringEncoder());

                  // 自己的邏輯Handler
                  pipeline.addLast("handler", new HelloWordServerHandler());
              }
          }

          服務(wù)器端的handler:

          public class HelloWordServerHandler extends ChannelInboundHandlerAdapter {

              @Override
              public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                  System.out.println(ctx.channel().remoteAddress()+"===>server: "+msg.toString());
                  ctx.write("received your msg");
                  ctx.flush();
              }

              @Override
              public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
                  super.exceptionCaught(ctx, cause);
                  ctx.close();
              }
          }

          上面服務(wù)器端和客戶端的代碼都已經(jīng)寫完,下面我們先啟動服務(wù)端,然后啟動客戶端,程序中我是在客戶端讓手動輸入,輸入結(jié)束之后回車,服務(wù)器端即可接受數(shù)據(jù)。

          客戶端:

          服務(wù)端:






          關(guān)注Java技術(shù)棧看更多干貨



          獲取 Spring Boot 實(shí)戰(zhàn)筆記!
          瀏覽 60
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青操逼视频在线观看 | 三区四区欧美视频 | 国产无码黄色 | 青青草av网站 | 日皮视频在线观看免费 |