使用Netty代理,提高工作效率

来源:互联网 发布:网络拓扑发现算法 编辑:程序博客网 时间:2024/04/28 13:22


最近工作中负责银行监管系统的对接。在申请银行测试环境的时候,流程复杂繁琐,耗费时间长。  我负责开发和测试银行的接口,但是开发阶段必须连接银行环境,但是银行环境又不能直接到本地。如果指定了本地端口,等测试验收时环境又不一样。银行回复给我们消息时服务地址又要改变,申请银行更改端口流程又负责。所以想在开发阶段和测试验收阶段使用同一个服务端,我采用了代理的方式。



当在本地local 端想通过中间proxy 来发送和接收请求到银行remote端,就可以使用代理。 就像我们平时使用的vpn一样,连接到vpn服务器上,然后通vpn服务器来转发和接收你的请求。

在netty的example中就有简单的例子。我的例子就是从里面改变而来。


ProxyConfig.properties 配置端口:

localIp=221.228.241.106localPort=8443    ProxyIp  =192.168.2.13ProxyPort =54951remoteIp=202.108.57.118remotePort=35053
HexDumpProxy.java  代理服务器端:

public final class HexDumpProxy{private static Logger logger = LoggerFactory.getLogger(HexDumpProxy.class);//中间IP和端口static final String PROXY_IP =ProxyConfig.getInstance().getProxyIp();static final int PROXY_PORT = Integer.parseInt(ProxyConfig.getInstance().getProxyPort());public static void main(String[] args) throws Exception{        logger.info("**********************启动代理 ********************** Ip:{} port:{}",PROXY_IP,PROXY_PORT);EventLoopGroup bossGroup = new NioEventLoopGroup(1);EventLoopGroup workerGroup = new NioEventLoopGroup();try{   //这里启动代理服务器端,用来接收local端和remote端的消息//把从来自local端的消息转发到remote端//把从来自remote端的消息转发到local端ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO)).childHandler(new HexDumpProxyInitializer()).childOption(ChannelOption.AUTO_READ, false).bind(new InetSocketAddress(PROXY_IP, PROXY_PORT))  //代理端口.sync().channel().closeFuture().sync();}finally{bossGroup.shutdownGracefully();workerGroup.shutdownGracefully();}}}
HexDumpProxyInitializer.java 文件 主要处理proxy服务器的handler

public class HexDumpProxyInitializer extends ChannelInitializer<SocketChannel>{public HexDumpProxyInitializer(){}@Overridepublic void initChannel(SocketChannel ch){ch.pipeline().addLast(new LoggingHandler(LogLevel.INFO),new HexDumpProxyFrontendHandler());}}


在HexDumpProxy 中主要关注HexDumpProxyFrontendHandler该类主要处理连接事件和数据的读取写入事件。

public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter {private static Logger logger =LoggerFactory.getLogger(HexDumpProxyFrontendHandler.class);        //写入银行的通道    private volatile Channel outbound2BankChannel;       public HexDumpProxyFrontendHandler() {         }    //当local或者remote与proxy连接时,proxy会发起到local或者remote端的连接    @Override    public void channelActive(ChannelHandlerContext ctx) {        final Channel inboundChannel = ctx.channel();        InetSocketAddress address = (InetSocketAddress)inboundChannel.remoteAddress();        logger.info("============连接代理成功==================");        logger.info("channelActive  IP:{} port:{}",address.getHostString(),address.getPort());    // Start the connection attempt.    Bootstrap b = new Bootstrap();    b.group(inboundChannel.eventLoop())    .channel(ctx.channel().getClass())    .option(ChannelOption.AUTO_READ, true)    .handler(new ChannelInitializer<SocketChannel>() {            @Override            public void initChannel(SocketChannel ch) throws Exception {                ChannelPipeline p = ch.pipeline();                               //p.addLast(new LoggingHandler(LogLevel.INFO));                p.addLast(new HexDumpProxyBackendHandler(inboundChannel),new LoggingHandler(LogLevel.INFO));            }        });    ChannelFuture f = b.connect(ProxyConfig.getInstance().getRemoteIp(), Integer.parseInt(ProxyConfig.getInstance().getRemotePort()));    outbound2BankChannel = f.channel();        f.addListener(new ChannelFutureListener() {    @Override    public void operationComplete(ChannelFuture future) {    if (future.isSuccess()) {    // connection complete start to read first data    inboundChannel.read();    } else {    // Close the connection if the connection attempt has failed.    inboundChannel.close();    }    }    });        }   //当从local或者remote写入到proxy时,proxy把读取到的数据直接写入到local或者remote端    @Override    public void channelRead(final ChannelHandlerContext ctx, Object msg) {    logger.debug("==============向目标服务器写入数据========================");    InetSocketAddress fromAddress = (InetSocketAddress)ctx.channel().remoteAddress();    logger.debug("数据来自:{}",fromAddress.getHostName());        if (outbound2BankChannel.isActive()) {    outbound2BankChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {    @Override    public void operationComplete(ChannelFuture future) {    if (future.isSuccess()) {    InetSocketAddress toAddress = (InetSocketAddress)outbound2BankChannel.remoteAddress();    logger.debug("数据发往:{}",toAddress.getHostName());    // was able to flush out data, start to read the next chunk    ctx.channel().read();    } else {    future.channel().close();    }    }    });    }    }    @Override    public void channelInactive(ChannelHandlerContext ctx) {    Channel ch = ctx.channel();    InetSocketAddress address = (InetSocketAddress)ch.remoteAddress();    logger.info("=============与代理服务器端口断开连接==================");    logger.info("channelInactive  IP:{} port:{}",address.getHostString(),address.getPort());        if (outbound2BankChannel != null) {    closeOnFlush(outbound2BankChannel);    }    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {    Channel ch = ctx.channel();    InetSocketAddress address = (InetSocketAddress)ch.remoteAddress();    logger.info("=============与代理服务器端口端口连接==================");    logger.info("exceptionCaught  IP:{} port:{}",address.getHostString(),address.getPort());        cause.printStackTrace();        closeOnFlush(ctx.channel());    }    /**     * Closes the specified channel after all queued write requests are flushed.     */    static void closeOnFlush(Channel ch) {        if (ch.isActive()) {              ch.flush();        }    }}

HexDumpProxyBackendHandler.java 文件主要负责数据的搬运。

public class HexDumpProxyBackendHandler extends ChannelInboundHandlerAdapter {private static Logger logger =LoggerFactory.getLogger(HexDumpProxyBackendHandler.class);  //写入本地的通道    private volatile Channel outbound2LocalChannel;            public HexDumpProxyBackendHandler(Channel outbound2LocalChannel)     {       this.outbound2LocalChannel =outbound2LocalChannel;    }   //当proxy与local或者remote连接时,开始从proxy中读取数据    @Override    public void channelActive(ChannelHandlerContext ctx) {    final Channel inboundChannel = ctx.channel();        InetSocketAddress address = (InetSocketAddress)inboundChannel.remoteAddress();    logger.info("##################代理连接目标端口成功#######################");    logger.info("连接目标端口成功。 ip:{} port:{}",address.getHostName(),address.getPort());        ctx.read();    }    //把proxy中的数据读取,同时把数据写入local或者remote端    @Override    public void channelRead(final ChannelHandlerContext ctx, Object msg) {    logger.info("##################目标服务器向代理写入数据#######################");     InetSocketAddress fromAddress = (InetSocketAddress)ctx.channel().remoteAddress();    logger.debug("数据来自:{}",fromAddress.getHostName());    outbound2LocalChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() {            @Override            public void operationComplete(ChannelFuture future) {                if (future.isSuccess()) {            InetSocketAddress toAddress = (InetSocketAddress)outbound2LocalChannel.remoteAddress();logger.debug("数据发往:{}",toAddress.getHostName());                    ctx.channel().read();                } else {                    future.channel().close();                }            }        });    }    @Override    public void channelInactive(ChannelHandlerContext ctx) {    logger.info("############代理和目标地址端口断开连接##############");        HexDumpProxyFrontendHandler.closeOnFlush(ctx.channel());    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {    logger.info("############代理和目标地址端口断开连接##############");    logger.debug("exceptionCaught:{}",cause.getMessage());        cause.printStackTrace();        HexDumpProxyFrontendHandler.closeOnFlush(ctx.channel());    }}



0 0
原创粉丝点击