【Netty4】深入學習Netty
阿新 • • 發佈:2018-11-26
Netty is an asynchronous event-driven network application framework
for rapid development of maintainable high performance protocol servers & clients
學習前,建議瞭解下java NIO相關知識,有助於對Netty中物件的理解。
NIO介紹,部落格地址:https://blog.csdn.net/the_fool_/article/details/83000648
AIO、BIO、NIO的區別,部落格地址: https://blog.csdn.net/anxpp/article/details/51512200
Netty如何封裝Java NIO,部落格地址::https://blog.csdn.net/tjreal/article/details/79751342
應用場景:https://blog.csdn.net/LIAN_XL/article/details/79799072
版本:目前最新版本為4.1.30
環境:JDK 5 (Netty 3.x) or 6 (Netty 4.x) is enough
八卦:Netty5被幹掉的原因?極大增加了複雜度,效率卻沒有提升,作者幹掉了master分支。
模組,結構:
支援的連結型別:普通連結、長連線、心跳檢測等。
使用:官方的簡單demo,用於介紹Netty 建立過程:
完整程式碼:https://blog.csdn.net/the_fool_/article/details/80611148
1、根據實際業務建立handle處理類,處理客戶端請求實際資訊:
package com.xxx.ann.netty.mostsimple; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; /** * Handles a server-side channel. * 實際上自定義的業務流程使用的是本類 */ public class DiscardServerHandler extends ChannelInboundHandlerAdapter { // (1) /** * Server讀取資訊的方法 * @param ctx * @param msg */ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) { ByteBuf in = (ByteBuf) msg; try { while (in.isReadable()) { // (1) System.out.print((char) in.readByte()); System.out.flush(); } // 向客戶端傳送訊息 String response = "hello client!"; // 在當前場景下,傳送的資料必須轉換成ByteBuf陣列 ByteBuf encoded = ctx.alloc().buffer(4 * response.length()); encoded.writeBytes(response.getBytes()); ctx.write(encoded); ctx.flush(); } finally { ReferenceCountUtil.release(msg); // (2) } } /** * 處理異常 * @param ctx * @param cause */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // (4) // Close the connection when an exception is raised. cause.printStackTrace(); ctx.close(); } }
2、Server 端程式碼:
package com.xxx.ann.netty.mostsimple;
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;
/**
* server 端
*/
public class DiscardServer {
private int port;
public DiscardServer(int port){
this.port=port;
}
public void run() throws Exception{
/**EventLoopGroup:IO操作的多執行緒組
*boss:
* accepts an incoming connection 處理連結
*worker:
* handles the traffic of the accepted connection once
* the boss accepts the connection and registers the accepted
* connection to the worker 處理實際邏輯
* 使用多少執行緒以及如何將它們對映到建立的通道取決於EventLoopGroup實現,甚至可以通過建構函式進行配置。
* */
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
/**ServerBootstrap是一個建立伺服器的助手類。可以直接使用通道設定伺服器。
*/
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
/**Here, we specify to use the NioServerSocketChannel class which is used to
* instantiate a new Channel to accept incoming connections.*/
.channel(NioServerSocketChannel.class)
/***
* 這裡指定處理程式將始終由新接受的通道進行處理
* ChannelInitializer:是專門幫助使用者配置新通道的特殊處理程式。
* 實際使用需要抽取到頂級類並自定義業務邏輯程式碼
*/
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
/**特定通道實現引數,具體含義:https://netty.io/4.1/api/io/netty/channel/ChannelOption.html
*option() is for the NioServerSocketChannel that accepts incoming connections
* childOption() is for the Channels accepted by the parent ServerChannel
* */
.option(ChannelOption.SO_BACKLOG, 128)
.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.
* */
f.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
workerGroup.shutdownGracefully();
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port=8081;
new DiscardServer(port).run();
}
}
3、瀏覽器進入licalhost:8081或者telnet localhost 8081可訪問服務端,可在控制檯檢視到已經建立連線並訪問成功(本demo不會成功返回資料)。