netty 客户端 实现断开重连

1、首先引入依赖

<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.6.Final</version>
</dependency>

2、创建server层代码

2.1、编写服务端代码

public static void main(String[] args) {
	new Thread(()->{
	    NioEventLoopGroup bossGroup = new NioEventLoopGroup();
	    NioEventLoopGroup workGroup = new NioEventLoopGroup();
	    try {
	        ServerBootstrap bootstrap = new ServerBootstrap();
	        bootstrap.group(bossGroup,workGroup)
	                .channel(NioServerSocketChannel.class)
	                .option(ChannelOption.SO_BACKLOG,128)
	                .childOption(ChannelOption.SO_KEEPALIVE,true)
	                .childHandler(new ServerChannelInitializer());
	        ChannelFuture channelFuture = bootstrap.bind(8099).sync();
	        channelFuture.channel().closeFuture().sync();
	    }catch (Exception e){
	    }finally {
	        bossGroup.shutdownGracefully();
	        workGroup.shutdownGracefully();
	    }
	}).start();
}

2.2、创建childHandler处理接收handler

public static class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new IdleStateHandler(10,10,10, TimeUnit.SECONDS));
        pipeline.addLast(new ReadHandler());
        pipeline.addLast(new WriteHandler());
        pipeline.addLast(new ServerSendHandler());
    }
}

2.3、创建公共的读写处理器

public static class ReadHandler extends SimpleChannelInboundHandler<ByteBuf>{
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        System.out.println("from : "+ctx.channel().remoteAddress()+" data : "+ ByteBufUtil.hexDump(msg));
        msg.retain();
        ctx.fireChannelRead(msg);
    }
}

public static class WriteHandler extends ChannelOutboundHandlerAdapter{
    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        if (msg instanceof ByteBuf){
            ByteBuf buf = (ByteBuf)msg;
            System.out.println("to : "+ctx.channel().remoteAddress()+" data : "+ByteBufUtil.hexDump(buf));
            super.write(ctx, msg, promise);
        }
    }
}

2.4、创建服务端的简单业务处理器

public static class ServerSendHandler extends SimpleChannelInboundHandler<ByteBuf> {
    
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        private static AtomicInteger atomicInteger = new AtomicInteger(1);

    	//这里简单模拟消息发送
        int a = msg.readInt();
        long b = msg.readLong();
        System.out.println("server ---- a:"+a +"  b:"+b);

        ByteBuf buffer = Unpooled.buffer();
        buffer.writeInt(atomicInteger.getAndIncrement());
        buffer.writeLong(170);
        ctx.writeAndFlush(buffer);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        System.out.println("server disconnect "+ctx.channel().remoteAddress());
        ctx.channel().disconnect();
        ctx.fireChannelInactive();
    }

    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (IdleStateEvent.class.isAssignableFrom(evt.getClass())) {
            IdleState state = ((IdleStateEvent) evt).state();
            if (state == IdleState.READER_IDLE) {
                // 读空闲超时,断开连接
                System.out.println("Channel read timeout, remote address:" + ctx.channel().remoteAddress().toString());
                ctx.close();
            } else if (state == IdleState.WRITER_IDLE) {
                ByteBuf buffer = Unpooled.buffer();
                buffer.writeInt(101);
                buffer.writeLong(171);
                ctx.writeAndFlush(buffer);
                System.out.println("Channel write timeout, remote address:" + ctx.channel().remoteAddress().toString());

            }
        }

        super.userEventTriggered(ctx, evt);
    }

}

3、创建客户端代码连接

3.1、编写客户端代码

public static void main(String[] args) {
    new Thread(()->{
        client(new NioEventLoopGroup());
    }).start();
}
 public static void client(NioEventLoopGroup group){
     Bootstrap bootstrap = new Bootstrap();
     bootstrap.group(group)
             .channel(NioSocketChannel.class)
             .option(ChannelOption.SO_KEEPALIVE,true)
             .handler(new ClientChannelInitializer());
     try {
         bootstrap.connect("127.0.0.1",8099).addListener(new ClientChannelListener()).sync();
     } catch (InterruptedException e) {
         e.printStackTrace();
     }
 }

2.2、创建handler处理接收handler

public static class ClientChannelInitializer extends ChannelInitializer<SocketChannel>{
  @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new IdleStateHandler(10,10,10, TimeUnit.SECONDS));
        pipeline.addLast(new ReadHandler());
        pipeline.addLast(new WriteHandler());
        pipeline.addLast(new ClientActHandler());
    }
}

3.3、创建客户端的简单业务处理器实现断线重连

public static class ClientActHandler extends SimpleChannelInboundHandler<ByteBuf>{
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
        ByteBuf buffer = Unpooled.buffer();
        buffer.writeInt(99);
        buffer.writeLong(180);
        ctx.writeAndFlush(buffer);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
        int a = msg.readInt();
        long b = msg.readLong();
        System.out.println("client : "+a+"  "+b);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        super.channelInactive(ctx);
        System.out.println("重新建立新的连接。。。。。");
        client(new NioEventLoopGroup());
    }
}

3.3、客户端监听器

public static class ClientChannelListener implements ChannelFutureListener{
    @Override
     public void operationComplete(ChannelFuture future) throws Exception {
         boolean success = future.isSuccess();
         if (success){
             System.out.println("connect success ");
         }else {
             System.out.println("connect error");
         }
     }
 }

4、结果输出

可以看到因为读超时服务端断开连接,然后客户端又重新连接

服务端

在这里插入图片描述

客户端

在这里插入图片描述

Netty 中,实现客户端重连可以通过以下几个步骤: 1. 创建一个连接管理器类来管理客户端的连接状态。 2. 在连接管理器中,创建一个定时任务,用于定期检查连接状态并重连。 3. 当连接断开时,通过监听器或回调方法得到通知。 4. 在断开的情况下,触发重连逻辑,重新连接到服务器。 下面是一个简单的示例代码,演示了如何在 Netty 客户端实现重连: ```java import io.netty.bootstrap.Bootstrap; import io.netty.channel.*; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import java.util.concurrent.TimeUnit; public class ReconnectClient { private final String host; private final int port; private final Bootstrap bootstrap; private final EventLoopGroup eventLoopGroup; private volatile boolean reconnecting; public ReconnectClient(String host, int port) { this.host = host; this.port = port; this.bootstrap = new Bootstrap(); this.eventLoopGroup = new NioEventLoopGroup(); this.reconnecting = false; bootstrap.group(eventLoopGroup) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override public void initChannel(SocketChannel ch) { ch.pipeline().addLast(new MyHandler()); } }); } public void connect() { try { ChannelFuture future = bootstrap.connect(host, port).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { // 处理异常 } finally { if (!reconnecting) { eventLoopGroup.shutdownGracefully(); } } } public void reconnect() { if (reconnecting) { return; } reconnecting = true; eventLoopGroup.schedule(() -> { try { ChannelFuture future = bootstrap.connect(host, port).sync(); future.channel().closeFuture().sync(); } catch (InterruptedException e) { // 处理异常 } finally { reconnecting = false; reconnect(); // 递归调用重新连接 } }, 5, TimeUnit.SECONDS); } public static void main(String[] args) { ReconnectClient client = new ReconnectClient("localhost", 8080); client.connect(); } } class MyHandler extends ChannelInboundHandlerAdapter { @Override public void channelInactive(ChannelHandlerContext ctx) { // 连接断开时的处理逻辑 ReconnectClient client = new ReconnectClient("localhost", 8080); client.reconnect(); } // 其他处理方法... } ``` 上述示例中,`ReconnectClient` 类封装了客户端的连接管理和重连逻辑。在 `connect` 方法中,首次建立连接并等待关闭;当连接断开时,会触发 `channelInactive` 方法,在该方法中调用 `reconnect` 方法进行重连。`reconnect` 方法使用定时任务调度,在一定时间后尝试重新连接,并通过递归调用实现了持续的重连。 这只是一个简单的示例,并未考虑异常处理、连接失败的情况等。在实际应用中,你可能需要根据具体需求进行适当的修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值