本文僅適用與Netty4.0.32版本,其餘版本是否適用表示並不清楚...bootstrap
Netty服務器啓動流程:緩存
一、建立線程池服務器
建立處理鏈接的線程池:bossGroup
建立處理全部事件的線程池:workerGroupsocket
EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup();
二、設定輔助啓動類。ServerBootStrap
傳入1中開闢的線程池
指定鏈接該服務器的channel類型
指定須要執行的childHandler
設置部分參數,如AdaptiveRecvByteBufAllocator緩存大小
.Option用於設置bossGroup相關參數
.childOption用於設置workerGroup相關參數ide
2.五、此處可處理一個問題:超長字符串在服務端handler沒法被一次接收完
可經過此句進行設置:.childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, MAX_LENGTH_OF_MSG, 65536))oop
ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class)//設置channel類型 .childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, MAX_LENGTH_OF_MSG, 65536)) .childHandler(new childChannelHandler());//選擇執行handler
此處的MAX_LENGTH_OF_MSG必須爲2的次冪,否則確定不會是你設置的那個值,具體會變成什麼,源碼還沒看,等看了再補充...編碼
2.7五、構建Handler處理流程spa
樣例以下:.net
public class childChannelHandler extends ChannelInitializer<SocketChannel>{ @Override protected void initChannel(SocketChannel ch) throws Exception { //TODO 添加各類功能handler 消息加解密,消息規範檢測,構建返回碼 ch.pipeline().addLast(new NettyServerHandler()); } }
當要添加多個handler時,就必須注意添加的順序。線程
這裏的handler分爲兩種類型:
一種繼承ChannelInboundHandler,用於處理來自客戶端的消息,好比對客戶端的消息進行解碼,讀取等等。該類型在pipeline中的執行順序與添加順序一致。
一種繼承ChannelOutboundHandler,用於處理即將發往客戶端的消息,好比對該消息進行編輯,編碼等等。該類型在pipeline中的執行順序與添加順序相反。
並且ChannelOutboundHandler的全部handler,放在ChannelInboundHandler下面是執行不到的。
好比:
public class childChannelHandler extends ChannelInitializer<SocketChannel>{ @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new OutboundHandler1()); //handler1 ch.pipeline().addLast(new OutboundHandler2()); //handler2 ch.pipeline().addLast(new InboundHandler1()); //handler3 ch.pipeline().addLast(new InboundHandler2()); //handler4 } }
以上4個handler的實際執行順序分別爲handler3 -> handler4 -> handler2 ->handler1
若是在handler4下方加上OutboundHandler3,那麼這個handler是不會被執行到的。
三、同步等待綁定指定端口
此處可屢次執行bind語句綁定多個端口
ChannelFuture channelFuture = serverBootstrap.bind(8080).sync(); channelFuture = serverBootstrap.bind(8081).sync(); ...
四、同步等待服務器關閉信息
channelFuture.channel().closeFuture().sync();
五、最後關閉此前開闢的兩個線程池
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
最後整段服務器代碼以下:
package Netty; 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; import io.netty.channel.AdaptiveRecvByteBufAllocator; public class NettyServer { public void startServerInPort(int port) throws Exception{ EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ //設置啓動輔助類 ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class)//設置channel類型 .childOption(ChannelOption.RCVBUF_ALLOCATOR, new AdaptiveRecvByteBufAllocator(64, 2048, 65536)) .childHandler(new childChannelHandler());//選擇執行handler //阻塞等待服務器徹底啓動 ChannelFuture channelFuture = serverBootstrap.bind(port).sync(); channelFuture.channel().closeFuture().sync(); }finally{ bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public class childChannelHandler extends ChannelInitializer<SocketChannel>{ @Override protected void initChannel(SocketChannel ch) throws Exception { //TODO 添加各類功能handler 消息加解密,消息規範檢測,構建返回碼 ch.pipeline().addLast(new NettyServerHandler()); } } }
客戶端的這部分代碼和服務器端差很少,就不另開一文囉嗦了。之間貼代碼:
import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; public class NettyClient { public void sendMsgToServer() throws Exception{ EventLoopGroup group = new NioEventLoopGroup(); try{ //設置輔助啓動類信息 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class)//選擇channel類型 .option(ChannelOption.TCP_NODELAY, true) .handler(new childChannelHandler()); //阻塞等待成功鏈接服務器 ChannelFuture channelFuture = bootstrap.connect(localhost,8000).sync(); //阻塞等待來自服務器的處理結果 channelFuture.channel().closeFuture().sync(); }finally{ group.shutdownGracefully(); } } private class childChannelHandler extends ChannelInitializer<SocketChannel>{ @Override protected void initChannel(SocketChannel ch) throws Exception { //TODO 添加其餘功能處理Handler,如消息加解密 ch.pipeline().addLast(new NettyClientHandler()); } } }