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

原创 2016年06月05日 19:03:13


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



当在本地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());
    }
}



使用Netty代理你的请求

本文由 ImportNew - 刘海波 翻译自 mastertheboss。如需转载本文,请先参见文章末尾处的转载要求。 你是否在寻找一个代理来调试你的客户端-服务端的通讯?不需要再寻觅!Net...
  • guomei
  • guomei
  • 2014年03月04日 00:25
  • 1081

基于netty实现的socks5代理协议

socks5协议 简介 socks5协议是一个标准的代理协议,工作在网络的四层,理论上可以代理任意应用层协议。协议标准RFC1928,用户/密码鉴权标准RFC1929。协议的中文版本可以参...
  • h254532699
  • h254532699
  • 2017年01月10日 13:16
  • 1709

java通过netty实现代理服务器

因为是用BIO的一个连接一个线程去处理,对于HTTP这种短连接协议来说CPU开销是非常大的,就算加入了线程池也不能完美解决BIO的缺陷,所以可以用NIO进行服务器的优化,NIO基于IO多路复用以实现单...
  • libraryhu
  • libraryhu
  • 2018年01月10日 16:42
  • 62

Proxifier+SecureCRT 实现代理+动态端口转发

1:Proxifier设置 1.1:代理服务器配置 配置文件-->代理服务器:输入地址(127.0.0.1),端口(16202),协议(SOCKS 版本5) 1.2:代理规则配置 配置文件...
  • fdsfdf3434
  • fdsfdf3434
  • 2017年10月23日 16:57
  • 232

在Netty中支持https服务器

一、生成测试证书      1、安装Openssl           sudo apt-get install openssl      2、生成证书(openssl生成证书 - feng...
  • fba529635
  • fba529635
  • 2015年08月25日 09:24
  • 5424

基于Netty的RPC简单框架实现(一):RPC客户端

1.RPC是什么 RPC 的全称是 Remote Procedure Call 是一种进程间通信方式。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个...
  • qq_31146969
  • qq_31146969
  • 2015年09月08日 16:50
  • 4179

Netty实现shadowsocks客户端

shadowsocks是什么 shadowsocks是基于socks5协议实现的代理方式,分为服务器和客户端,双端之间通过使用指定的加密方式(AES,BlowFish,Table等)进行数据传输,有效...
  • codingo2016
  • codingo2016
  • 2016年09月14日 12:53
  • 916

Practical Netty (5) TCP反向代理服务器

Practical Netty (5) TCP反向代理服务器作者:柳大·Poechant(钟超)邮箱:zhongchao.ustc#gmail.com(# -> @)博客:Blog.CSDN.net/...
  • Poechant
  • Poechant
  • 2013年01月11日 13:46
  • 13714

Netty 使用安全的连接即HTTPS连接

当需要使用安全的连接即HTTPS连接时,需配置SslHandler到ChannelPipeline,SslHandler无需另外写出,调用NETTY封装的即可,传入的SSLEngine在下面生成 p...
  • chen846262292
  • chen846262292
  • 2017年01月23日 11:08
  • 3010

Netty中的那些坑

最近开发了一个纯异步的redis客户端,算是比较深入的使用了一把netty。在使用过程中一边优化,一边解决各种坑。而这些坑大部分基本上是Netty 4对Netty 3的改进部分引起的。 注:这里...
  • xtqve
  • xtqve
  • 2015年06月11日 09:10
  • 1369
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:使用Netty代理,提高工作效率
举报原因:
原因补充:

(最多只允许输入30个字)