Netty學習_Netty框架入門教程:Netty入門之HelloWorld實現

咱們可能都學過Socket通訊/io/nio/aio等的編程。若是想把Socket真正的用於實際工做中去,那麼還須要不斷的完善、擴展和優化。好比很經典的Tcp讀包寫包問題,或者是數據接收的大小,實際的通訊讀取與應答的處理邏輯等等。當細節問題須要咱們認真的去思考,而這些咱們都須要大量的時間和精力,以及豐富的經驗。html

 

因此想學好socket通訊不是件容易的事情。那麼如今,咱們就須要學習一門新的技術Nettyjava

 

咱們爲何選擇Netty?緣由是它簡單。咱們不再須要去編寫複雜的代碼和邏輯去實現通訊;咱們不再須要去考慮性能問題;咱們不再須要考慮編解碼問題、半包讀寫等問題。這些強大的功能Netty已經幫咱們實現了,咱們只須要使用它便可!編程

 

Netty是目前最流行的NIO框架,它的健壯性、功能、性能、可定製性和可擴展性在同類框架中都是數一數二的。bootstrap

 

Netty已經獲得成百上千的商業/商用項目驗證,如Hadoop的RPC框架Avro、以及咱們以後學習的JMS框架,強大的RocketMQ、還有主流的分佈式通訊框架Dubbox等等。安全

 

Netty5廢棄的緣由
Netty5可能底層有一些小問題,可能版本更新太快了,而後他把Netty5起了一個分支叫Netty4.1。服務器

 

Netty架構圖網絡


Netty特性架構

設計:各類傳輸類型,阻塞和非阻塞的套接字統一的API使用靈活簡單但功能強大的線程模型無鏈接的DatagramSocket支持鏈邏輯,易於重用。框架

易於使用:提供大量的文檔例子,處理依賴JDK1.6+,沒有其餘任何的依賴關係,某些功能依賴JDK1.7+,其餘特定可能有相關依賴,但都是可選的!socket

性能:比Java APIS更好的吞吐量和更低的延遲,由於線程池和重用因此消耗較小的資源,儘可能減小沒必要要的內存拷貝。

健壯性:健壯性鏈接快或慢或超載不會致使更多的內存溢出錯誤,在高速的網絡環境中不會不公平的讀或寫

安全性:完整的SSL/TLS和StartTLS支持能夠在OSGI等的受限制的環境中運行。

社區:版本發佈頻繁,社區活躍。

 

對應Netty的介紹就到這裏,下面使用Netty框架實現一個HelloWorld。

 

第一步:下載Netty的jar包

這裏使用的是Netty4.1版本。官網下載地址:https://netty.io/downloads.html

 

第二步:新建java工程

一、新建一個java工程,按照下圖新建4個類

二、新建一個lib目錄並把Netty的jar包拷貝到該目錄

三、把jar包添加到環境變量

 

第三步:編寫ServerHandler類代碼,代碼以下

 1 package netty.helloworld;
 2 
 3 import io.netty.buffer.ByteBuf;
 4 import io.netty.buffer.Unpooled;
 5 import io.netty.channel.ChannelHandlerContext;
 6 import io.netty.channel.ChannelInboundHandlerAdapter;
 7 
 8 public class ServerHandler extends ChannelInboundHandlerAdapter {
 9     @Override
10     public void channelActive(ChannelHandlerContext ctx) throws Exception {
11         System.out.println("server channel active... ");
12     }
13     
14     @Override
15     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
16             ByteBuf buf = (ByteBuf) msg;
17             byte[] req = new byte[buf.readableBytes()];
18             buf.readBytes(req);
19             String body = new String(req, "utf-8");
20             System.out.println("Server :" + body );
21             String response = "進行返回給客戶端的響應:" + body;
22             ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));
23     }
24 
25     @Override
26     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
27         System.out.println("讀完了");
28         ctx.flush();
29     }
30 
31     @Override
32     public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {
33         ctx.close();
34     }
35 }
ServerHandler.java

 

第四步:編寫Server類代碼,代碼以下

 1 package netty.helloworld;
 2 
 3 import io.netty.bootstrap.ServerBootstrap;
 4 import io.netty.channel.ChannelFuture;
 5 import io.netty.channel.ChannelInitializer;
 6 import io.netty.channel.ChannelOption;
 7 import io.netty.channel.EventLoopGroup;
 8 import io.netty.channel.nio.NioEventLoopGroup;
 9 import io.netty.channel.socket.SocketChannel;
10 import io.netty.channel.socket.nio.NioServerSocketChannel;
11 
12 public class Server {
13     public static void main(String[] args) throws Exception {
14         // 1 建立線兩個程組 
15         // 一個是用於處理服務器端接收客戶端鏈接的
16         // 一個是進行網絡通訊的(網絡讀寫的)
17         EventLoopGroup pGroup = new NioEventLoopGroup();
18         EventLoopGroup cGroup = new NioEventLoopGroup();
19         
20         // 2 建立輔助工具類,用於服務器通道的一系列配置
21         ServerBootstrap b = new ServerBootstrap();
22         b.group(pGroup, cGroup)        // 綁定倆個線程組
23         .channel(NioServerSocketChannel.class)        // 指定NIO的模式
24         .option(ChannelOption.SO_BACKLOG, 1024)        // 設置tcp緩衝區
25         .option(ChannelOption.SO_SNDBUF, 32*1024)    // 設置發送緩衝大小
26         .option(ChannelOption.SO_RCVBUF, 32*1024)    // 這是接收緩衝大小
27         .option(ChannelOption.SO_KEEPALIVE, true)    // 保持鏈接
28         .childHandler(new ChannelInitializer<SocketChannel>() {
29             @Override
30             protected void initChannel(SocketChannel sc) throws Exception {
31                 // 3 在這裏配置具體數據接收方法的處理
32                 sc.pipeline().addLast(new ServerHandler());
33             }
34         });
35         
36         // 4 進行綁定 
37         ChannelFuture cf1 = b.bind(8888).sync();
38         // 5 等待關閉
39         cf1.channel().closeFuture().sync();
40         pGroup.shutdownGracefully();
41         cGroup.shutdownGracefully();
42     }
43 }
Server.java

 

第五步:編寫ClientHandler類代碼,代碼以下

 1 package netty.helloworld;
 2 
 3 import io.netty.buffer.ByteBuf;
 4 import io.netty.channel.ChannelHandlerContext;
 5 import io.netty.channel.ChannelInboundHandlerAdapter;
 6 import io.netty.util.ReferenceCountUtil;
 7 
 8 public class ClientHandler extends ChannelInboundHandlerAdapter {
 9     @Override
10     public void channelActive(ChannelHandlerContext ctx) throws Exception {}
11 
12     @Override
13     public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
14         try {
15             ByteBuf buf = (ByteBuf) msg;
16             
17             byte[] req = new byte[buf.readableBytes()];
18             buf.readBytes(req);
19             
20             String body = new String(req, "utf-8");
21             System.out.println("Client :" + body );
22         } finally {
23             ReferenceCountUtil.release(msg);
24         }
25     }
26 
27     @Override
28     public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {}
29 
30     @Override
31     public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
32         ctx.close();
33     }
34 }
ClientHandler.java

 

第六步:編寫Client類代碼,代碼以下

 1 package netty.helloworld;
 2 
 3 import io.netty.bootstrap.Bootstrap;
 4 import io.netty.buffer.Unpooled;
 5 import io.netty.channel.ChannelFuture;
 6 import io.netty.channel.ChannelInitializer;
 7 import io.netty.channel.EventLoopGroup;
 8 import io.netty.channel.nio.NioEventLoopGroup;
 9 import io.netty.channel.socket.SocketChannel;
10 import io.netty.channel.socket.nio.NioSocketChannel;
11 
12 public class Client {
13     public static void main(String[] args) throws Exception{
14         EventLoopGroup group = new NioEventLoopGroup();
15         Bootstrap b = new Bootstrap();
16         b.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {
17             @Override
18             protected void initChannel(SocketChannel sc) throws Exception {
19                 sc.pipeline().addLast(new ClientHandler());
20             }
21         });
22         
23         ChannelFuture cf1 = b.connect("127.0.0.1", 8888).syncUninterruptibly();
24         // 發送消息
25         byte[] msg = "發送第1條測試消息".getBytes();
26         cf1.channel().writeAndFlush(Unpooled.copiedBuffer(msg));
27         
28         // 等待關閉
29         cf1.channel().closeFuture().sync();
30         group.shutdownGracefully();
31     }
32 }
Client.java

 

第七步:啓動Server服務

 

 

最後一步:啓動客戶端

 

 

控制檯輸出

 

關於Netty框架學習的第一節課就講到這裏,其餘更多關於Netty方面的教程後續會陸續更新!!

end -- 1346ac475e98aed

須要索取完整源碼或者其餘任何有關技術問題和疑問,直接wxhaox

相關文章
相關標籤/搜索