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


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

 

所以想學好socket通信不是件容易的事情。那么現在,我們就需要學習一門新的技術Netty

 

我們為什么選擇Netty?原因是它簡單。我們再也不需要去編寫復雜的代碼和邏輯去實現通信;我們再也不需要去考慮性能問題;我們再也不需要考慮編解碼問題、半包讀寫等問題。這些強大的功能Netty已經幫我們實現了,我們只需要使用它即可!

 

Netty是目前最流行的NIO框架,它的健壯性、功能、性能、可定制性和可擴展性在同類框架中都是首屈一指的。

 

Netty已經得到成百上千的商業/商用項目驗證,如Hadoop的RPC框架Avro、以及我們之后學習的JMS框架,強大的RocketMQ、還有主流的分布式通信框架Dubbox等等。

 

Netty5廢棄的原因
Netty5可能底層有一些小問題,可能版本更新太快了,然后他把Netty5起了一個分支叫Netty4.1。

 

Netty架構圖


Netty特性

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

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

性能:比Java APIS更好的吞吐量和更低的延遲,因為線程池和重用所以消耗較小的資源,盡量減少不必要的內存拷貝。

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

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

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

 

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

 

第一步:下載Netty的jar包

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

 

第二步:新建java工程

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

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

3、把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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM