简介

我们知道proxy 是提出的一个代理协议,通过这个协议,所有实现这个协议的proxy或者LBS,都可以附带真实客户端的IP地址和端口号,这使得proxy 在实际应用中非常有用。

haproxy_haproxy跨域配置_haproxyacl

这么优秀的协议,没有理由netty不支持。本文将会谈一下netty中对proxy 代理协议的支持。

netty对proxy 协议的支持

proxy 协议其实很简单,就是在请求前面带了proxy 信息。

在netty中这个信息叫做:

public final class HAProxyMessage extends AbstractReferenceCounted {
复制代码

是一个,这一点和很类似,说明保留着和很类似的特性。

根据proxy 协议,该协议可以分为两个版本,分别是v1和v2,其中v1版本是文本协议,而v2版本支持二进制的格式。

显然从代码编写和调试的角度来看v1更加友好,但是从程序的角度来看,v2可能性能更高。

中有个专门的on类,来表示proxy 的版本信息:

public enum HAProxyProtocolVersion {
    V1(VERSION_ONE_BYTE),
    V2(VERSION_TWO_BYTE);
复制代码

on是一个枚举类,在它里面定义了和proxy协议相对应的两个版本号。

在版本号之后是,在netty中用来表示:

public enum HAProxyCommand {
    LOCAL(HAProxyConstants.COMMAND_LOCAL_BYTE),
    PROXY(HAProxyConstants.COMMAND_PROXY_BYTE);
复制代码

也是一个枚举类,里面定义了两个的值,分别是local和proxy。

其中local表示该请求是代理服务器主动发起的,而不是客户端发起的,比如监控检测等请求。

proxy表示该请求是一个代理请求。

接下来是和,这两个字段用同一个byte来表示,所以这两个类都是ol的内部类。

先看下的定义:

    public enum AddressFamily {
        AF_UNSPEC(AF_UNSPEC_BYTE),
        AF_IPv4(AF_IPV4_BYTE),
        AF_IPv6(AF_IPV6_BYTE),
        AF_UNIX(AF_UNIX_BYTE);
复制代码

中定义了4个 类型,分别是,ipv4,ipv6和unix。分别对应未知,ipv4,ipv6和unix 。

再看下的定义:

    public enum TransportProtocol {
        UNSPEC(TRANSPORT_UNSPEC_BYTE),
        STREAM(TRANSPORT_STREAM_BYTE),
        DGRAM(TRANSPORT_DGRAM_BYTE);
复制代码

有3个值,分别是,和dgram。分别对应未知协议,http/https协议,udp/tcp协议。

因为和实际上是同一个byte,所以经过组合之后可以得到下面的几个枚举值:

    UNKNOWN(TPAF_UNKNOWN_BYTE, AddressFamily.AF_UNSPEC, TransportProtocol.UNSPEC),
    TCP4(TPAF_TCP4_BYTE, AddressFamily.AF_IPv4, TransportProtocol.STREAM),
    TCP6(TPAF_TCP6_BYTE, AddressFamily.AF_IPv6, TransportProtocol.STREAM),
    UDP4(TPAF_UDP4_BYTE, AddressFamily.AF_IPv4, TransportProtocol.DGRAM),
    UDP6(TPAF_UDP6_BYTE, AddressFamily.AF_IPv6, TransportProtocol.DGRAM),
    UNIX_STREAM(TPAF_UNIX_STREAM_BYTE, AddressFamily.AF_UNIX, TransportProtocol.STREAM),
    UNIX_DGRAM(TPAF_UNIX_DGRAM_BYTE, AddressFamily.AF_UNIX, TransportProtocol.DGRAM);
复制代码

以上的枚举值也是ol中定义的值。

接下来就是源ip地址,目标的ip地址,源端口和目标端口这几个值,定义为属性表示如下:

    private final String sourceAddress;
    private final String destinationAddress;
    private final int sourcePort;
    private final int destinationPort;
复制代码

最后,proxy 中还可以包含额外的字段tlv,tlv在netty中也是一种,使用表示:

public class HAProxyTLV extends DefaultByteBufHolder 
复制代码

因为tlv是key value结构,所以看下的构造函数:

    public HAProxyTLV(Type type, ByteBuf content) {
        this(type, Type.byteValueForType(type), content);
    }
复制代码

接受一个type和的value。

Type是一个枚举类,在netty中可以支持下面的值:

    public enum Type {
        PP2_TYPE_ALPN,
        PP2_TYPE_AUTHORITY,
        PP2_TYPE_SSL,
        PP2_TYPE_SSL_VERSION,
        PP2_TYPE_SSL_CN,
        PP2_TYPE_NETNS,
        OTHER;
复制代码

在中,tlv是一个list来保存的:

private final List tlvs;
复制代码

到此,所有所需要的参数都齐了,我们看下的构造函数:

    public HAProxyMessage(
            HAProxyProtocolVersion protocolVersion, HAProxyCommand command, HAProxyProxiedProtocol proxiedProtocol,
            String sourceAddress, String destinationAddress, int sourcePort, int destinationPort,
            List tlvs)
复制代码

会将所有的参数都存储到本地的变量中,供后续使用。

因为proxy 有两个版本,v1和v2,所以中提供了两个将编码为对象的方法,分别是:

static HAProxyMessage decodeHeader(ByteBuf header) 
复制代码

和:

static HAProxyMessage decodeHeader(String header)
复制代码

有了proxy 的java表示之后,我们再来看一下的编码解码器。

的编码解码器

netty对对象的支持表现在两个地方,netty提供了两个类分别对进行编码和解码,这两个类是r和r。

先看一下r:

public final class HAProxyMessageEncoder extends MessageToByteEncoder 
复制代码

r继承自,传入的泛型是,表示是将编码成为。

它的方法很简单,根据传入的版本信息,分别进行编码:

    protected void encode(ChannelHandlerContext ctx, HAProxyMessage msg, ByteBuf out) throws Exception {
        switch (msg.protocolVersion()) {
            case V1:
                encodeV1(msg, out);
                break;
            case V2:
                encodeV2(msg, out);
                break;
            default:
                throw new HAProxyProtocolException("Unsupported version: " + msg.protocolVersion());
        }
    }
复制代码

r是跟r相反的动作,是将接收到的解析成为:

public class HAProxyMessageDecoder extends ByteToMessageDecoder 
复制代码

因为有两个版本,那么怎么判断接收到的是哪个版本呢?

其实很简单,因为v1版本和v2版本的开始字符是不一样的,v1版本的开头是一个text:”PROXY”, v2版本的开头是一个固定的二进制串,如下所示:

    static final byte[] BINARY_PREFIX = {
            (byte) 0x0D,
            (byte) 0x0A,
            (byte) 0x0D,
            (byte) 0x0A,
            (byte) 0x00,
            (byte) 0x0D,
            (byte) 0x0A,
            (byte) 0x51,
            (byte) 0x55,
            (byte) 0x49,
            (byte) 0x54,
            (byte) 0x0A
    };
    static final byte[] TEXT_PREFIX = {
            (byte) 'P',
            (byte) 'R',
            (byte) 'O',
            (byte) 'X',
            (byte) 'Y',
    };
复制代码

看下它的方法实现:

    protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List out) throws Exception {
        if (version == -1) {
            if ((version = findVersion(in)) == -1) {
                return;
            }
        }
        ByteBuf decoded;
        if (version == 1) {
            decoded = decodeLine(ctx, in);
        } else {
            decoded = decodeStruct(ctx, in);
        }
        if (decoded != null) {
            finished = true;
            try {
                if (version == 1) {
                    out.add(HAProxyMessage.decodeHeader(decoded.toString(CharsetUtil.US_ASCII)));
                } else {
                    out.add(HAProxyMessage.decodeHeader(decoded));
                }
            } catch (HAProxyProtocolException e) {
                fail(ctx, null, e);
            }
        }
    }
复制代码

上面代码的逻辑是先从中根据版本号出信息放到中。
然后再根据版本号的不同,分别调用的两个不同版本的方法进行解码。最终得到。
netty中proxy 的代码示例
有了netty对proxy 的支持,那么在netty中搭建支持proxy 的服务器和客户端就很容易了。
先看一下如何搭建支持proxy 的服务器:
    private static void startServer(int port) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
             .channel(NioServerSocketChannel.class)
             .handler(new LoggingHandler(LogLevel.INFO))
             .childHandler(new ServerInitializer());
            b.bind(port).sync().channel().closeFuture().sync();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
复制代码

代码和常规的netty 一样,这里使用了和el,搭建了一个支持TCP协议的netty服务器。
中包含了netty自带的编码器和自定义的消息处理器:
class ServerInitializer extends ChannelInitializer {
    @Override
    public void initChannel(SocketChannel ch) throws Exception {
        ch.pipeline().addLast(
                new LoggingHandler(LogLevel.DEBUG),
                new HAProxyMessageDecoder(),
                new SimpleChannelInboundHandler() {
                    @Override
                    protected void channelRead0(ChannelHandlerContext ctx, Object msg) {
                        if (msg instanceof HAProxyMessage) {
                            log.info("proxy message is : {}", msg);
                        } else if (msg instanceof ByteBuf) {
                            log.info("bytebuf message is : {}", ByteBufUtil.prettyHexDump((ByteBuf) msg));
                        }
                    }
                });
    }
}
复制代码

这里使用netty自带的r,用来将消息解码为,然后在自定义的中对进行处理。
这里的服务器可以处理两种消息,一种是,一种是原始的。处理的结果就是将消息打印出来。
然后看下客户端的定义:
EventLoopGroup group = new NioEventLoopGroup();
            Bootstrap b = new Bootstrap();
            b.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ClientHander());
            Channel ch = b.connect(host, port).sync().channel();
复制代码

客户端使用的是和,是基于TCP协议的请求。
这里添加了自定义的:,继承自用来对发出的消息进行处理。
这里看一下它的方法:
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        ctx.pipeline().addBefore(ctx.name(), null, HAProxyMessageEncoder.INSTANCE);
        super.handlerAdded(ctx);
    }
复制代码

可以看到方法向中添加了r,用于编码。
因为对于一个来说,只需要用到一次,后续的正常消息就不需要这个编码器了,所以我们需要在write方法中监听的状态,如果写入成功之后,就从中移出r和。
    public void write(final ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        ChannelFuture future1 = ctx.write(msg, promise);
        if (msg instanceof HAProxyMessage) {
            future1.addListener((ChannelFutureListener) future2 -> {
                if (future2.isSuccess()) {
                    ctx.pipeline().remove(HAProxyMessageEncoder.INSTANCE);
                    ctx.pipeline().remove(ClientHander.this);
                } else {
                    ctx.close();
                }
            });
        }
    }
复制代码

最后我们构建了一个虚拟的,然后通过netty客户端进行发送:
HAProxyMessage message = new HAProxyMessage(
                    HAProxyProtocolVersion.V2, HAProxyCommand.PROXY, HAProxyProxiedProtocol.TCP4,
                    "127.0.0.1", "127.0.0.2", 8000, 9000);
            ch.writeAndFlush(message).sync();
            ch.writeAndFlush(Unpooled.copiedBuffer("this is a proxy protocol message!", CharsetUtil.UTF_8)).sync();
            ch.close().sync();
复制代码

总结
上面的代码只是一个简单的模拟proxy 在netty中的使用情况,并不代表上面的代码就可以在实际的项目中应用了。如果你想使用的话,可以在下面的代码上面继续丰富和完善。
本文的代码,大家可以参考:
learn-
原文链接:
———END———
限 时 特 惠: 本站每日持续更新海量各大内部创业教程,永久会员只需109元,全站资源免费下载 点击查看详情
站 长 微 信: nanadh666

			
	声明:1、本内容转载于网络,版权归原作者所有!2、本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。3、本内容若侵犯到你的版权利益,请联系我们,会尽快给予删除处理!
		

		
		

	
			haproxyprotocolversion, haproxycommand, transportprotocol, addressfamily, unspec
	
		


	
		
		
						
				
				娜娜            
            		

		
			
						分享
			
						收藏
			
						点赞(0)
			
		
	



	


		
	
	    
		  		  	
			    
			      免费下载或者VIP会员资源能否直接商用?
			      本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
			    
			
	    		  	
			    
			      提示下载完但解压或打开不了?
			      最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。 若排除这种情况,可在对应资源底部留言,或联络我们。
			    
			
	    		  	
			    
			      找不到素材资源介绍文章里的示例图片?
			      对于会员专享、整站源码、程序插件、网站模板、网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
			    
			
	    		  	
			    
			      付款后无法显示下载地址或者无法查看内容?
			      如果您已经成功付款但是网站没有弹出成功提示,请联系站长提供付款信息为您处理
			    
			
	    		  	
			    
			      购买该资源后,可以退款吗?
			      源码素材属于虚拟商品,具有可复制性,可传播性,一旦授予,不接受任何形式的退款、换货要求。请您在购买获取之前确认好 是您所需要的资源
			    
			
	    		

	
	
	



			
			
			


    
                
            
                
                
                    上一篇
                    5个PPT必备网站,图片、图标、配色、模板一次性搞定!看到就是赚
                
            
        
                        
            
                
                    下一篇
                    我翻遍了全网PPT素材库!整理了10000+小图标,都是阿里官方出品
                
                
            
        
            
			
			

   相关文章
   
    

    



	
		

			
				
				
			
			
			
			
			


	

		
		
		
	
			
									生活百科
				
				
					小米帐号密码忘记了怎么激活设备
				

									如果你忘记了小米帐号的密码,并且想激活设备,不要担心!在本文中,我们将为您提供一...
				
				


		1 年前
	
		0
	
		0
	
		4.1K
	
	
			
		
	



    



	
		

			
				
				
			
			
			
			
			


	

		
		
		
	
			
									生活百科
				
				
					京东微信打白条是什么意思
				

									京东微信打白条是指在京东网上商城中,通过微信支付使用白条功能购买商品的一种支付方...
				
				


		1 年前
	
		0
	
		0
	
		3.3K
	
	
			
		
	



    



	
		

			
				
				
			
			
			
			
			


	

		
		
		
	
			
									生活百科
				
				
					市教育局领导视察格兰德小学
				

									,市教育局领导视察格兰德小学
				
				


		9 月前
	
		0
	
		0
	
		2.1K
	
	
			
		
	



    



	
		

			
				
				
			
			
			
			
			


	

		
		
		
	
			
									生活百科
				
				
					192.168.1.253路由器设置(Router模式)
				

									192.168.1.253路由器设置(Router模式)。在Router(无线路...
				
				


		6 月前
	
		0
	
		0
	
		2.2K
	
	
			
		
	

    


			
		

		
			
				站长简介			微信:nanadh666
公众号:娜娜创业日记
QQ群:278210989
本人创业10年,多家网站VIP付费会员,本站分享创业项目、创业教程、主题源码、电商教程、工具软件等也不断的从淘宝购买很多教程和模板。 做了这个网站用来分享这些精品付款资源。

		
最新实战项目


  
    
      

        
          
        

        
          
            
              微头条变现写作课程,掌握流量变现技巧,提升微头条质量,实现收益增长
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              AI+自媒体运营变现课,掌握AI写作与RPA技术,轻松实现自媒体变现
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              微信朋友圈 广告投放全攻略:ADQ平台介绍、推广层级、商品库与营销目标
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              人工智能AI时代,饭碗频遭抢夺,普通人咋办?躺赢之道在何方?
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              图书博主养成记:4类带货方式,视频直播课助力,快速入局图文赛道
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              YouTube视频营销入门:账号注册指南,平台介绍与外贸推广
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              小红书飞书 模板实战变现:小红书快速起号,搭建一个赚钱的飞书模板
            
          
        

      
    

  
    
      

        
          
        

        
          
            
              联盟营销实战指南,详解联盟模式、平台规则及联盟客运作,实现流量变现
            
          
        

      
    

  

			
		

	











    	    

		



  
    
          
    
    

	          	            

    同步各大论坛VIP资源,创业教程、自媒体、抖音快手短视频等视频教程以及营销软件、源码、淘宝虚拟资源等,长期更新各大付费创业项目
  

  
    快速导航
    
      实战项目免费项目自动项目网站源码    
  

  
    关于本站
    
      VIP介绍合伙人介绍客服咨询推广计划    
  

  
    联系我们
    
微信客服
扫码加我微信


微信公众号
关注公众号
  

		
	

		
			网站地图      Copyright © 2023 本站为非盈利性赞助网站,本站所有软件来自互联网,版权属原著所有,如有侵权,敬请来信联系我们,我们立即删除。 - All rights reserved
			闽ICP备2023013435/*@media (min-width: 768px){*/
/*.py-md-4 {*/
/*    padding-top: 1.5rem!important;*/
/*    padding-bottom: 0rem!important;*/
/*}}*/




		
	


	
			








	
		
			首页会员介绍用户中心		
	




	
		
			首页实战项目开通VIP我的加盟合伙人		
	




  
  
  
  
    

	          	            


  
  首页
实战项目
免费项目
自动项目
开通会员限时5折
加盟合伙人
APP下载
生活百科









var zb = {"home_url":"https:\/\/www.taonana.cn","ajax_url":"https:\/\/www.taonana.cn\/wp-admin\/admin-ajax.php","theme_url":"https:\/\/www.taonana.cn\/wp-content\/themes\/ripro-v5","singular_id":"54659","post_content_nav":"0","site_popup_login":"1","site_notify_auto":"0","current_user_id":"0","ajax_nonce":"b0935e85b9","gettext":{"__copypwd":"\u5bc6\u7801\u5df2\u590d\u5236\u526a\u8d34\u677f","__copybtn":"\u590d\u5236","__copy_succes":"\u590d\u5236\u6210\u529f","__comment_be":"\u63d0\u4ea4\u4e2d...","__comment_succes":"\u8bc4\u8bba\u6210\u529f","__comment_succes_n":"\u8bc4\u8bba\u6210\u529f\uff0c\u5373\u5c06\u5237\u65b0\u9875\u9762","__buy_be_n":"\u8bf7\u6c42\u652f\u4ed8\u4e2d\u00b7\u00b7\u00b7","__buy_no_n":"\u652f\u4ed8\u5df2\u53d6\u6d88","__is_delete_n":"\u786e\u5b9a\u5220\u9664\u6b64\u8bb0\u5f55\uff1f"}};



        
(function(){
var el = document.createElement("script");
el.src = "https://lf1-cdn-tos.bytegoofy.com/goofy/ttzz/push.js?b38fc1b4a0668a7c2cb975bbb26fef3329ce400567c1e04f47289e3a62667c923d72cd14f8a76432df3935ab77ec54f830517b3cb210f7fd334f50ccb772134a";
el.id = "ttzz";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(el, s);
})(window)



(function(){
var el = document.createElement("script");
el.src = "https://lf1-cdn-tos.bytegoofy.com/goofy/ttzz/push.js?ebded415054d3b078cff74cc51db0700195bafea6b214600891dbd43de6b68ccfd9a9dcb5ced4d7780eb6f3bbd089073c2a6d54440560d63862bbf4ec01bba3a";
el.id = "ttzz";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(el, s);
})(window)


var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?c8bfa035760d88c8c595bdba887f3e8a";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();





  var ndt = $("#help dt");
  var ndd = $("#help dd");
  ndd.eq(0).show();
  ndt.click(function () {
    ndd.hide();
    $(this).next().show();
  });