斷線重接更好用的 *** netty斷線重連原理( 二 )


TcpClient —— TCP貫穿的存戶端
public class TcpClient { private String host; private int port; private Bootstrap bootstrap; /** 將<code>Channel</code>生存起來, 可用來在其余非handler的場合發送數據 */ private Channel channel; public TcpClient(String host, int port) { this(host, port, new ExponentialBackOffRetry(1000, Integer.MAX_VALUE, 60 * 1000)); } public TcpClient(String host, int port, RetryPolicy retryPolicy) { this.host = host; this.port = port; init(); } /** * 向長途TCP效勞器乞求貫穿 */ public void connect() { synchronized (bootstrap) { ChannelFuture future = bootstrap.connect(host, port); this.channel = future.channel(); } } private void init() { EventLoopGroup group = new NioEventLoopGroup(); // bootstrap 可重用, 只需在TcpClient范例化的功夫初始化即可. bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ClientHandlersInitializer(TcpClient.this)); } public static void main(String[] args) { TcpClient tcpClient = new TcpClient("localhost", 2222); tcpClient.connect(); }}Server端
ServerIdleStateTrigger —— 斷連觸發器
/** * <p>在規則功夫內未收到存戶端的任何數據包, 將積極割斷該貫穿</p> */public class ServerIdleStateTrigger extends ChannelInboundHandlerAdapter { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { if (evt instanceof IdleStateEvent) { IdleState state = ((IdleStateEvent) evt).state(); if (state == IdleState.READER_IDLE) { // 在規則功夫內沒有收到存戶端的下行數據, 積極割斷貫穿 ctx.disconnect(); } } else { super.userEventTriggered(ctx, evt); } }}ServerBizHandler —— 效勞器端的交易處置器
/** * <p>收到來自存戶端的數據包后, 徑直在遏制臺打字與印刷出來.</p> */@ChannelHandler.Sharablepublic class ServerBizHandler extends SimpleChannelInboundHandler<String> { private final String REC_HEART_BEAT = "I had received the heart beat!"; @Override protected void channelRead0(ChannelHandlerContext ctx, String data) throws Exception { try { System.out.println("receive data: " + data);// ctx.writeAndFlush(REC_HEART_BEAT); } catch (Exception e) { e.printStackTrace(); } } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println("Established connection with the remote client."); // do something ctx.fireChannelActive(); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println("Disconnected with the remote client."); // do something ctx.fireChannelInactive(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}ServerHandlerInitializer —— 效勞器端處置器匯合的初始化類
/** * <p>用來初始化效勞器端波及到的一切<code>Handler</code></p> */public class ServerHandlerInitializer extends ChannelInitializer<SocketChannel> { protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast("idleStateHandler", new IdleStateHandler(5, 0, 0)); ch.pipeline().addLast("idleStateTrigger", new ServerIdleStateTrigger()); ch.pipeline().addLast("frameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4)); ch.pipeline().addLast("frameEncoder", new LengthFieldPrepender(4)); ch.pipeline().addLast("decoder", new StringDecoder()); ch.pipeline().addLast("encoder", new StringEncoder()); ch.pipeline().addLast("bizHandler", new ServerBizHandler()); }}注:new IdleStateHandler(5, 0, 0)該handler代辦即使在5秒內沒有收到來自存戶端的任何數據包(囊括但不限于心跳包),將會積極割斷與該存戶端的貫穿 。
TcpServer —— 效勞器端
public class TcpServer { private int port; private ServerHandlerInitializer serverHandlerInitializer; public TcpServer(int port) { this.port = port; this.serverHandlerInitializer = new ServerHandlerInitializer(); } public void start() { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) .childHandler(this.serverHandlerInitializer); // 綁定端口,發端接受進入的貫穿 ChannelFuture future = bootstrap.bind(port).sync(); System.out.println("Server start listen at " + port); future.channel().closeFuture().sync(); } catch (Exception e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); e.printStackTrace(); } } public static void main(String[] args) throws Exception { int port = 2222; new TcpServer(port).start(); }}至此,一切代碼仍舊編寫結束 。
嘗試
開始啟用存戶端,再啟用效勞器端 。啟用實行后,在存戶端的遏制臺上,不妨看到打字與印刷如次一致日記:
存戶端遏制臺輸入的日記
在效勞器端不妨看到遏制臺輸入了一致如次的日記:

推薦閱讀