Netty实现TCP转发

130 阅读1分钟

一、背景

公司网络部分故障,测试环境某些网段到Oracle连接失败,排查修复慢,故整了个TCP链接转发工具,放到好的网段去进行转发,使开发业务流程不中断。

二、引入依赖

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

三、实现代码

public class TCPForwardingServer {

    Bootstrap bootstrap;
    ServerBootstrap server;

    NioEventLoopGroup bossGroup;
    NioEventLoopGroup workGroup;

    public static void main(String[] args) {
        TCPForwardingServer TCPForwardingServer = new TCPForwardingServer();
        TCPForwardingServer.init();
    }

    class DataHandler extends ChannelInboundHandlerAdapter {

        private Channel channel;

        public DataHandler(Channel channel) {
            this.channel = channel;
        }

        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            ByteBuf readBuffer = (ByteBuf) msg;
            readBuffer.retain();
            channel.writeAndFlush(readBuffer);
            readBuffer.release();
        }

    }

    void init() {
        this.bossGroup = new NioEventLoopGroup();
        this.workGroup = new NioEventLoopGroup();
        this.server = new ServerBootstrap();
        this.bootstrap = new Bootstrap();
        bootstrap.channel(NioSocketChannel.class);
        bootstrap.group(bossGroup);
        this.server.group(bossGroup, workGroup);


        server.channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>(
                ) {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast("serverHandler", new DataHandler(getClientChannel(socketChannel)));
                    }
                }).option(ChannelOption.SO_BACKLOG, 1024)
                .option(ChannelOption.SO_RCVBUF, 16 * 1024);

        // 监听地址
        server.bind(1521).syncUninterruptibly().addListener((ChannelFutureListener) channelFuture -> {
            if (channelFuture.isSuccess()) {
                System.out.println("forward server start success");
            } else {
                System.out.println("forward server start failed");
            }
        });
    }

    private Channel getClientChannel(SocketChannel ch) throws InterruptedException {
        this.bootstrap.handler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast("clientHandler", new DataHandler(ch));
            }
        });
        // 目标地址
        ChannelFuture sync = bootstrap.connect("目标地址域名/ip", 1521).sync();
        return sync.channel();
    }

}