Netty官方示例
阿新 • • 發佈:2018-10-22
不同的 har ava object keepalive amp 信息 lang nbsp
一、DEMO
官方並沒有使用Hello World來作為一個例子,而是采用RFC的DISCARD,這個協議定義了就是接收到請求後什麽也不幹。
第一步編寫DiscardServerHandler類:
package io.netty.example.discard; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; //ChannelInboundHandlerAdapter實現自ChannelInboundHandler //ChannelInboundHandler提供了不同的事件處理方法你可以重寫 public class DiscardServerHandler extends ChannelInboundHandlerAdapter { /* * @說明:該方法用於接收從客戶端接收的信息 * @時間:2017-4-2下午12:25:05 * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object) * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //Discard the received data silently //ByteBuf是一個引用計數對象實現ReferenceCounted,他就是在有對象引用的時候計數+1,無的時候計數-1,當為0對象釋放內存 ByteBuf in=(ByteBuf)msg; try { while(in.isReadable()){ System.out.println((char)in.readByte()); System.out.flush(); } } finally { ReferenceCountUtil.release(msg); } } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
第二步編寫DiscardServer:
package io.netty.example.discard; import io.netty.bootstrap.ServerBootstrap; 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; public class DiscardServer { private int port; public DiscardServer(int port){ this.port = port; } public void run() throws Exception{ //Group:群組,Loop:循環,Event:事件,這幾個東西聯在一起,相比大家也大概明白它的用途了。 //Netty內部都是通過線程在處理各種數據,EventLoopGroup就是用來管理調度他們的,註冊Channel,管理他們的生命周期。 //NioEventLoopGroup是一個處理I/O操作的多線程事件循環 //bossGroup作為boss,接收傳入連接 //因為bossGroup僅接收客戶端連接,不做復雜的邏輯處理,為了盡可能減少資源的占用,取值越小越好 EventLoopGroup bossGroup=new NioEventLoopGroup(1); //workerGroup作為worker,處理boss接收的連接的流量和將接收的連接註冊進入這個worker EventLoopGroup workerGroup=new NioEventLoopGroup(); try { //ServerBootstrap負責建立服務端 //你可以直接使用Channel去建立服務端,但是大多數情況下你無需做這種乏味的事情 ServerBootstrap b=new ServerBootstrap(); b.group(bossGroup, workerGroup) //指定使用NioServerSocketChannel產生一個Channel用來接收連接 .channel(NioServerSocketChannel.class) //ChannelInitializer用於配置一個新的Channel //用於向你的Channel當中添加ChannelInboundHandler的實現 .childHandler(new ChannelInitializer<SocketChannel>() { public void initChannel(SocketChannel ch) throws Exception { //ChannelPipeline用於存放管理ChannelHandel //ChannelHandler用於處理請求響應的業務邏輯相關代碼 ch.pipeline().addLast(new DiscardServerHandler()); }; }) //對Channel進行一些配置 //註意以下是socket的標準參數 //BACKLOG用於構造服務端套接字ServerSocket對象,標識當服務器請求處理線程全滿時,用於臨時存放已完成三次握手的請求的隊列的最大長度。如果未設置或所設置的值小於1,Java將使用默認值50。 //Option是為了NioServerSocketChannel設置的,用來接收傳入連接的 .option(ChannelOption.SO_BACKLOG, 128) //是否啟用心跳保活機制。在雙方TCP套接字建立連接後(即都進入ESTABLISHED狀態)並且在兩個小時左右上層沒有任何數據傳輸的情況下,這套機制才會被激活。 //childOption是用來給父級ServerChannel之下的Channels設置參數的 .childOption(ChannelOption.SO_KEEPALIVE, true); // Bind and start to accept incoming connections. ChannelFuture f=b.bind(port).sync(); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to gracefully // shut down your server. //sync()會同步等待連接操作結果,用戶線程將在此wait(),直到連接操作完成之後,線程被notify(),用戶代碼繼續執行 //closeFuture()當Channel關閉時返回一個ChannelFuture,用於鏈路檢測 f.channel().closeFuture().sync(); }finally{ //資源優雅釋放 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { int port=8088; try { new DiscardServer(port).run(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
二、ECHO協議的DEMO
ECHO協議,定義了客戶端請求啥就返回啥
第一步編寫EchoServerHandler:
package io.netty.example.echo; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class EchoServerHandler extends ChannelInboundHandlerAdapter { /* * @說明:該方法用於接收從客戶端接收的信息 * @時間:2017-4-8下午12:08:51 * @see io.netty.channel.ChannelInboundHandlerAdapter#channelRead(io.netty.channel.ChannelHandlerContext, java.lang.Object) * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { //ChannelHandlerContext提供各種不同的操作用於觸發不同的I/O時間和操作 //調用write方法來逐字返回接收到的信息 //這裏我們不需要在DISCARD例子當中那樣調用釋放,因為Netty會在寫的時候自動釋放 //只調用write是不會釋放的,它會緩存,直到調用flush ctx.write(msg); ctx.flush(); //你可以直接使用writeAndFlush(msg) //ctx.writeAndFlush(msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
第二步編寫EchoServer:
package io.netty.example.echo; import io.netty.bootstrap.ServerBootstrap; 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; public class EchoServer { private int port; public EchoServer(int port){ this.port = port; } public void run() throws Exception{ //NioEventLoopGroup是一個處理I/O操作的多線程事件循環 //bossGroup作為boss,接收傳入連接 //bossGroup只負責接收客戶端的連接,不做復雜操作,為了減少資源占用,取值越小越好 //Group:群組,Loop:循環,Event:事件,這幾個東西聯在一起,相比大家也大概明白它的用途了。 //Netty內部都是通過線程在處理各種數據,EventLoopGroup就是用來管理調度他們的,註冊Channel,管理他們的生命周期。 EventLoopGroup bossGroup=new NioEventLoopGroup(1); //workerGroup作為worker,處理boss接收的連接的流量和將接收的連接註冊進入這個worker EventLoopGroup workerGroup=new NioEventLoopGroup(); try { //ServerBootstrap負責建立服務端 //你可以直接使用Channel去建立服務端,但是大多數情況下你無需做這種乏味的事情 ServerBootstrap b=new ServerBootstrap(); b.group(bossGroup, workerGroup) //指定使用NioServerSocketChannel產生一個Channel用來接收連接 .channel(NioServerSocketChannel.class) //ChannelInitializer用於配置一個新的Channel //用於向你的Channel當中添加ChannelInboundHandler的實現 .childHandler(new ChannelInitializer<SocketChannel>() { public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new EchoServerHandler()); }; }) //對Channel進行一些配置 //註意以下是socket的標準參數 //BACKLOG用於構造服務端套接字ServerSocket對象,標識當服務器請求處理線程全滿時,用於臨時存放已完成三次握手的請求的隊列的最大長度。如果未設置或所設置的值小於1,Java將使用默認值50。 //Option是為了NioServerSocketChannel設置的,用來接收傳入連接的 .option(ChannelOption.SO_BACKLOG, 128) //是否啟用心跳保活機制。在雙方TCP套接字建立連接後(即都進入ESTABLISHED狀態)並且在兩個小時左右上層沒有任何數據傳輸的情況下,這套機制才會被激活。 //childOption是用來給父級ServerChannel之下的Channels設置參數的 .childOption(ChannelOption.SO_KEEPALIVE, true); // Bind and start to accept incoming connections. ChannelFuture f=b.bind(port).sync(); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to gracefully // shut down your server. //sync()會同步等待連接操作結果,用戶線程將在此wait(),直到連接操作完成之後,線程被notify(),用戶代碼繼續執行 //closeFuture()當Channel關閉時返回一個ChannelFuture,用於鏈路檢測 f.channel().closeFuture().sync(); }finally{ //資源優雅釋放 bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { int port=8088; try { new EchoServer(port).run(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
三、依賴:
<!-- Netty開始 --> <!-- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>4.1.6.Final</version> </dependency> <!-- Netty結束 -->
來源:https://blog.csdn.net/wocjy/article/details/78661464
Netty官方示例