关闭

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

标签: netty proxynetty proxy代理netty proxy双向代理
1610人阅读 评论(6) 收藏 举报
分类:


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



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

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


ProxyConfig.properties 配置端口:

localIp=221.228.241.106
localPort=8443
    
ProxyIp  =192.168.2.13
ProxyPort =54951

remoteIp=202.108.57.118
remotePort=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()
	{
	}
	@Override
	public 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

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:121700次
    • 积分:2540
    • 等级:
    • 排名:第14957名
    • 原创:120篇
    • 转载:4篇
    • 译文:21篇
    • 评论:11条
    最新评论