Netty客户端断线重连服务端

Netty客户端重连机制

场景:
 1.Netty初次启动客户端,如果无法连接到服务端,将尝试重连。
 2.在客户端与服务端保持长连接的过程中,如果连接断开,尝试与服务端重连。

  1. 主要代码

     Netty客户端启动处理类

    @Service("nettyClient")
    public class NettyClient {
    	private final static Logger log = LoggerFactory.getLogger(NettyClient.class);
    	private EventLoopGroup loop = new NioEventLoopGroup();
    	
    	@Autowired
    	private NettyFilter nettyFilter;
    	
    	@Autowired
    	private AppConfig appConfig;
    	
    	public void run(){
    		doConnect(new Bootstrap(), loop);
    	}
    
    	/**
    	 * netty client 连接,连接失败10秒后重试连接
    	 */
    	public void doConnect(Bootstrap bootstrap, EventLoopGroup eventLoopGroup) {
    		ChannelFuture f = null;
    		try {
    			if (bootstrap != null) {
    				bootstrap.group(eventLoopGroup);
    				bootstrap.channel(NioSocketChannel.class);
    				bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
    				bootstrap.handler(nettyFilter);
    				bootstrap.remoteAddress(appConfig.getHost(), appConfig.getPort());
    				f = bootstrap.connect().addListener((ChannelFuture futureListener)->{
    					final EventLoop eventLoop = futureListener.channel().eventLoop();
    					if (!futureListener.isSuccess()) {
    						log.warn("客户端已启动,与服务端建立连接失败,10s之后尝试重连!");
    						eventLoop.schedule(() -> doConnect(new Bootstrap(), eventLoop), 10, TimeUnit.SECONDS);
    					}else {
    						log.info("客户端已启动成功,port:{},开始登录服务端",appConfig.getPort());
    					    // 可以在这发送登录成功的消息给server
    					    //futureListener.channel().writeAndFlush(Unpooled.copiedBuffer("msg!!!", CharsetUtil.UTF_8));
    
    					}
    				});
    			}
    		} catch (Exception e) {
    			log.error("连接客户端失败,error:" + e);
    		}
    	}
    }
    

     客户端与服务端心跳处理类,与客户端断开连接后的重试代码在channelInactive()这个方法中

    @Service("idleclienthandler")
    @ChannelHandler.Sharable
    public class IdleClientHandler extends SimpleChannelInboundHandler<MessageBase> {
    	private final static Logger logger = LoggerFactory.getLogger(IdleClientHandler.class);
    	private long heartbeatCount = 0;
    	
    	@Autowired
    	private NettyClient nettyClient;
    
    
    	@Override
    	public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
    		if (evt instanceof IdleStateEvent) {
    			IdleStateEvent event = (IdleStateEvent) evt;
    		 	logger.info(ctx.channel().remoteAddress() + ",超时类型:" + event.state());
    			sendPingMsg(ctx);
    		} else {
    			super.userEventTriggered(ctx, evt);
    		}
    	}
    
    	/**
    	 * 发送ping消息
    	 * @param context
    	 */
    	protected void sendPingMsg(ChannelHandlerContext context) {
    		MessageBase body = NettyMessage.MessageBase.newBuilder()
    				.setCmd(CommandType.PING)
    				.setPtcode(Cache.ptcode)
    				.setData("ping")
    				.build();
    		context.writeAndFlush(body);
    		heartbeatCount++;
    		logger.info("Client sent ping msg to " + context.channel().remoteAddress() + ", count: " + heartbeatCount);
    	}
    
    	/**
    	 * 处理断开重连
    	 */
    	@SuppressWarnings("static-access")
    	@Override
    	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
    		logger.info("与服务器连接断开,尝试重新连接...");
    		nettyClient.retryConnectFlag = true;
    		final EventLoop eventLoop = ctx.channel().eventLoop();  
    	    // 立即重连
    	    nettyClient.doConnect(new Bootstrap(), eventLoop);  
    		super.channelInactive(ctx);  
    	}
    
    	@Override
    	protected void channelRead0(ChannelHandlerContext ctx, MessageBase msg) throws Exception {
    		logger.info("收到的消息!{}",msg);
    	}
    }
    
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 11
    评论
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值