一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - Netty學習教程之基礎使用篇

Netty學習教程之基礎使用篇

2020-10-21 21:36荒野的塵埃 Java教程

Netty是由JBOSS提供的一個Java開源框架。Netty提供異步的、事件驅動的網絡應用程序框架和工具,用以快速開發高性能、高可靠性的網絡服務器和客戶端程序。下面這篇文章主要給大家介紹了關于Netty基礎使用的相關資料,需要的朋友

什么Netty

Netty是由JBOSS提供的一個java開源框架。Netty提供異步的、事件驅動的網絡應用程序框架和工具,用以快速開發高性能、高可靠性的網絡服務器和客戶端程序。

也就是說,Netty 是一個基于NIO的客戶、服務器端編程框架,使用Netty 可以確保你快速和簡單的開發出一個網絡應用,例如實現了某種協議的客戶,服務端應用。Netty相當簡化和流線化了網絡應用的編程開發過程,例如,TCP和UDP的socket服務開發。

我們下面編寫四個類

      1.用于接收數據的服務器端Socket

      2.用于接收客戶端的消息,用于接收和反饋客戶端發出的消息類ServertHandler

      3.用于發送數據的服務器端Client

      4.用于發送數據和接收服務器端發出的數據處理類ClientHandler

Socket.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.string.StringDecoder;
 
public class Server {
  
 public static void main(String[] args) throws InterruptedException {
  //1.第一個線程組是用于接收Client端連接的
  EventLoopGroup bossGroup = new NioEventLoopGroup();
  //2.第二個線程組是用于實際的業務處理的
  EventLoopGroup workerGroup = new NioEventLoopGroup();
  ServerBootstrap b = new ServerBootstrap();
  b.group(bossGroup, workerGroup);//綁定兩個線程池
  b.channel(NioServerSocketChannel.class);//指定NIO的模式,如果是客戶端就是NioSocketChannel
  b.option(ChannelOption.SO_BACKLOG, 1024);//TCP的緩沖區設置
  b.option(ChannelOption.SO_SNDBUF, 32*1024);//設置發送緩沖的大小
  b.option(ChannelOption.SO_RCVBUF, 32*1024);//設置接收緩沖區大小
  b.option(ChannelOption.SO_KEEPALIVE, true);//保持連續
  b.childHandler(new ChannelInitializer<SocketChannel>() {
   @Override
   protected void initChannel(SocketChannel sc) throws Exception {
    ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());//拆包粘包定義結束字符串(第一種解決方案)
    sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));//在管道中加入結束字符串
   // sc.pipeline().addLast(new FixedLengthFrameDecoder(200));第二種定長
    sc.pipeline().addLast(new StringDecoder());//定義接收類型為字符串把ByteBuf轉成String
    sc.pipeline().addLast(new ServertHandler());//在這里配置具體數據接收方法的處理
   }
  });
  ChannelFuture future = b.bind(8765).sync();//綁定端口
  future.channel().closeFuture().sync();//等待關閉(程序阻塞在這里等待客戶端請求)
  bossGroup.shutdownGracefully();//關閉線程
  workerGroup.shutdownGracefully();//關閉線程
 }
}

      1.在上面這個Server.java中,我們都要定義兩個線程池,boss和worker,boss是用于管理連接到server端的client的連接數的線程池,而woeker是用于管理實際操作的線程池。

      2.ServerBootstrap用一個ServerSocketChannelFactory 來實例化。ServerSocketChannelFactory 有兩種選擇,一種是NioServerSocketChannelFactory,一種是OioServerSocketChannelFactory。 前者使用NIO,后則使用普通的阻塞式IO。它們都需要兩個線程池實例作為參數來初始化,一個是boss線程池,一個是worker線程池。

      3.然后使ServerBookstrap管理boss和worker線程池。并且設置各個緩沖區的大小。

      4.這里的事件處理類經常會被用來處理一個最近的已經接收的Channel。ChannelInitializer是一個特殊的處理類,他的目的是幫助使用者配置一個新的Channel。也許你想通過增加一些處理類比如NettyServerHandler來配置一個新的Channel 或者其對應的ChannelPipeline來實現你的網絡程序。 當你的程序變的復雜時,可能你會增加更多的處理類到pipline上,然后提取這些匿名類到最頂層的類上。

      5.在使用原始的encoder、decoder的情況下,Netty發送接收數據都是按照ByteBuf的形式,其它形式都是不合法的。 而在上面這個Socket中,我使用sc.pipeline().addLast()這個方法設置了接收為字符串類型,注意:只能設置接收為字符串類型,發送還是需要發送ByteBuf類型的數據。而且在這里我還設置了以$_為結尾的字符串就代表了本次請求字符串的結束。

      6.通過b.bind綁定端口,用于監聽的端口號。

ServerHandler.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ServertHandler extends ChannelHandlerAdapter {
 
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  String body = (String) msg;
  System.out.println("server"+body);//前面已經定義了接收為字符串,這里直接接收字符串就可以
  //服務端給客戶端的響應
  String response= " hi client!$_";//發送的數據以定義結束的字符串結尾
  ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));//發送必須還是ByteBuf類型
 }
 
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
   cause.printStackTrace();
   ctx.close();
 }
  
}

ServertHandler繼承自 ChannelHandlerAdapter,這個類實現了ChannelHandler接口,ChannelHandler提供了許多事件處理的接口方法,然后你可以覆蓋這些方法。現在僅僅只需要繼承ChannelHandlerAdapter類而不是你自己去實現接口方法。

1.由于我們再server端開始的時候已經定義了接收類型為String,所以在這里我們接收到的msg直接強轉成String就可以了。同時也要定義以什么為一次請求的結尾。

Client.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class Client {
 
 public static void main(String[] args) throws InterruptedException {
  EventLoopGroup worker = new NioEventLoopGroup();
  Bootstrap b = new Bootstrap();
  b.group(worker)
  .channel(NioSocketChannel.class)
  .handler(new ChannelInitializer<SocketChannel>() {
   @Override
   protected void initChannel(SocketChannel sc) throws Exception {
    ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
    sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,buf));
    sc.pipeline().addLast(new StringDecoder());
    sc.pipeline().addLast(new ClientHandler());
   }
  });
  ChannelFuture f=b.connect("127.0.0.1",8765).sync();
  f.channel().writeAndFlush(Unpooled.copiedBuffer(" hi server2$_".getBytes()));
  f.channel().writeAndFlush(Unpooled.copiedBuffer(" hi server3$_".getBytes()));
  f.channel().writeAndFlush(Unpooled.copiedBuffer(" hi server4$_".getBytes()));
  f.channel().closeFuture().sync();
  worker.shutdownGracefully();
 }
}

client端和Socket端幾乎代碼相同,只是client端用的不是ServerBootstrap而是Bootstrap來管理連接。這里沒什么好說的。

ClientHandler.java

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ClientHandler extends ChannelHandlerAdapter{
 @Override
 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  try {
   System.out.println("client"+msg.toString());
  } finally {
   ReferenceCountUtil.release(msg);//釋放緩沖區
  }
 }
 
 @Override
 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
   cause.printStackTrace();
   ctx.close();
 }
}

ClientHandler和ServertHandler代碼和原理也是一樣,只是在client端我們要釋放緩沖區。為什么在ServerHandler我們不需要釋放呢 ?因為在ServertHandler我們調用ctx.writeAndFlush方法的時候,這個方法默認已經幫我們釋放了緩沖區。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:http://blog.csdn.net/a347911/article/details/53734255

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: www.俺去| 四虎影视在线影院在线观看观看 | 久久亚洲午夜牛牛影视 | 国产激情一区二区三区四区 | 成人亚洲精品一区 | 肉搏潘金莲三级18春 | 日韩免费毛片视频杨思敏 | 国产精品久久久久久久久久久久久久 | 欧美交换乱理伦片120秒 | 亚洲AV无码国产精品色在线看 | 国产成人免费观看在线视频 | 日本一道本中文字幕 | h版在线观看 | 国产精品短视频 | 4455永久在线观免费看片 | 亚洲高清国产拍精品动图 | 日本厕所spy2wc | 日本不卡一区二区三区在线观看 | 色交视频 | 国产高清经典露脸3p | 美女被灌浣肠失禁视频 | xxx老妇人60| 精品国产品香蕉在线观看75 | 999导航| 久青草国产97香蕉在线视频 | 久久99r66热这里只有精品 | 天使萌痴汉在线中文字幕 | 9久re在线观看视频精品 | 亚洲精品视频久久 | 毛片99| 麻麻与子乱肉小说怀孕 | 91精品国产美女福到在线不卡 | 麻豆网站视频国产在线观看 | waswaswas免费 | 99 久久99久久精品免观看 | 国产免费又粗又猛又爽视频国产 | 99热这里只有精品在线观看 | 国产日韩欧美成人 | 国产成人性毛片aaww | 午夜精品久久久久久久99 | 日韩 欧美 国产 亚洲 中文 |