netty系列之:一口多用,使用同一端口运行不同协议

作者&投稿:翟璐 (若有异议请与网页底部的电邮联系)
~ 在之前的文章中,我们介绍了在同一个netty程序中支持多个不同的服务,它的逻辑很简单,就是在一个主程序中启动多个子程序,每个子程序通过一个BootStrap来绑定不同的端口,从而达到访问不同端口就访问了不同服务的目的。

但是多个端口虽然区分度够高,但是使用起来还是有诸多不便,那么有没有可能只用一个端口来统一不同的协议服务呢?

今天给大家介绍一下在netty中使用同一端口运行不同协议的方法,这种方法叫做port unification。

在讲解自定义port unification之前,我们来看下netty自带的port unification,比如SocksPortUnificationServerHandler。

我们知道SOCKS的主要协议有3中,分别是SOCKS4、SOCKS4a和SOCKS5,他们属于同一种协议的不同版本,所以肯定不能使用不同的端口,需要在同一个端口中进行版本的判断。

具体而言,SocksPortUnificationServerHandler继承自ByteToMessageDecoder,表示是将ByteBuf转换成为对应的Socks对象。

那他是怎么区分不同版本的呢?

在decode方法中,传入了要解码的ByteBuf in,首先获得它的readerIndex:

我们知道SOCKS协议的第一个字节表示的是版本,所以从in ByteBuf中读取第一个字节作为版本号:

有了版本号就可以通过不同的版本号进行处理,具体而言,对于SOCKS4a,需要添加Socks4ServerEncoder和Socks4ServerDecoder:

对于SOCKS5来说,需要添加Socks5ServerEncoder和Socks5InitialRequestDecoder两个编码和解码器:

这样,一个port unification就完成了,其思路就是通过传入的同一个端口的ByteBuf的首字节,来判断对应的SOCKS的版本号,从而针对不同的SOCKS版本进行处理。

在本例中,我们将会创建一个自定义的Port Unification,用来同时接收HTTP请求和gzip请求。

在这之前,我们先看一下两个协议的magic word,也就是说我们拿到一个ByteBuf,怎么能够知道这个是一个HTTP协议,还是传输的一个gzip文件呢?

先看下HTTP协议,这里我们默认是HTTP1.1,对于HTTP1.1的请求协议,下面是一个例子:

HTTP请求的第一个单词就是HTTP请求的方法名,具体而言有八种方法,分别是:

OPTIONS
返回服务器针对特定资源所支持的HTTP请求方法。也可以利用向Web服务器发送'*'的请求来测试服务器的功能性。
HEAD
向服务器索要与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以在不必传输整个响应内容的情况下,就可以获取包含在响应消息头中的元信息。
GET
向特定的资源发出请求。注意:GET方法不应当被用于产生“副作用”的操作中,例如在Web Application中。其中一个原因是GET可能会被网络蜘蛛等随意访问。
POST
向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
PUT
向指定资源位置上传其最新内容。
DELETE
请求服务器删除Request-URI所标识的资源。
TRACE
回显服务器收到的请求,主要用于测试或诊断。
CONNECT
HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

那么需要几个字节来区分这八个方法呢?可以看到一个字节是不够的,因为我们有POST和PUT,他们的第一个字节都是P。所以应该使用2个字节来作为magic word。

对于gzip协议来说,它也有特殊的格式,其中gzip的前10个字节是header,其中第一个字节是0x1f,第二个字节是0x8b。

这样我们用两个字节也能区分gzip协议。

这样,我们的handler逻辑就出来了。首先从byteBuf中取出前两个字节,然后对其进行判断,区分出是HTTP请求还是gzip请求:

对应的,我们还需要对其添加相应的编码和解码器,对于gzip来说,netty提供了ZlibCodecFactory:

对于HTTP来说,netty也提供了HttpRequestDecoder和HttpResponseEncoder还有HttpContentCompressor来对HTTP消息进行编码解码和压缩。

添加了编码和解码器之后,如果你想自定义一些操作,只需要再添加自定义的对应的消息handler即可,非常的方便。

本文的例子可以参考: learn-netty4


微服务核心组件 Zuul 网关原理剖析
总结:zuul1.0时候当zuul接受到一个请求后会同步执行前置过滤器、路由过滤器、后置过滤器,等执行完毕后在同步把结果返回为调用方,调用方在整个过程中是阻塞的。其实SpringBoot集成的zuul就是自己实现了个前置过滤器做选择路由,然后自己实现了个路由过滤器根据前置过滤器选择的路由具体做路由转发。Netty...

dubbo系列之-qos运维-2021-01-17
qos 主要提供了ls,online,offline,help 功能,具体说,只有三种,上下线服务和查看服务 我们跟读一下源码,看看qos 服务的启动,请求处理,上下线等。在dubbo 生产者服务暴露和消费者消费引用的过程中都会启动qos,并且qos 通过cas来保证一个jvm只启动一次。同样qos 功能也是通过netty启动server,处理类指定...

微服务架构:基于微服务和Docker容器技术的PaaS云平台架构设计
微服务、Spring,MyBatis,Netty源码分析的朋友可以加我的Java高级交流:854630135,群里有阿里大牛直播讲解技术,以及Java大型互联网技术的视频免费分享给大家。 服务注册与发现 由于微服务架构是由一系列职责单一的细粒度服务构成的网状结构,服务之间通过轻量机制进行通信,这就引入了服务注册与发现的问题,服务的提供方要注册...

引擎的意思解释
网络引擎是用于开发网络应用程序的软件框架或库。它提供了一系列的网络协议和功能,用于实现网络通信、数据传输、安全认证等。网络引擎可以帮助开发者简化网络编程的复杂性,提供高效、稳定的网络连接。常见的网络引擎包括Socket、Netty等。引擎在不同领域中具有多种含义和应用,它们都在各自领域发挥着重要的...

Netty入门 -- 什么是Netty?
服务器启动时,Bootstrap会绑定端口并监听连接,确保成功或失败。而在关闭服务器时,优雅地调用shutdownGracefully方法,确保所有连接的处理完毕。对于客户端,NettyClient类同样简洁明了,通过NioSocketChannel连接服务器,定义事件循环和连接参数。执行一系列任务,包括发送消息、异步处理ChannelFuture,以及在连接...

Netty WebSocket 拆包浅析
看完 Netty 的源码实现,那么就可以进行实际的编码解决问题了。当服务端\/客户端发现包文过大时,会进行拆包。而为每个包定义一系列的定义。例如:当接收一个 Text 消息时, Netty 首先会实例化一个 TextWebSocketFrame 对象并传递给调用方,而通过  isFinalFragment 我们可以判断出,...

引擎在汽车中是什么作用?
网络引擎是用于开发网络应用程序的软件框架或库。它提供了一系列的网络协议和功能,用于实现网络通信、数据传输、安全认证等。网络引擎可以帮助开发者简化网络编程的复杂性,提供高效、稳定的网络连接。常见的网络引擎包括Socket、Netty等。引擎在不同领域中具有多种含义和应用,它们都在各自领域发挥着重要的...

慈利县15658256602: netty如何处理同一个端口上来的多条不同协议的数据,不分端口的情况下. -
伯音立迈: 65536 指的是端口数目 一台电脑只有 最多65536个端口.不能可能使用超过 65536 个端口的 .但是每个端口可比不是只能有一个连接的.一个 jvm 上保持 10万 ~ 50万 的长连接 指的是连接数,这么多连接使用的一个或者几十个端口,而不是所有的端口.web服务 用80端口 每秒几万人访问的时候,并不是没人一个端口而是大家公用一个80端口的.

慈利县15658256602: 怎么使用netty写一个http长连接服务器 -
伯音立迈: 我又看了下play的源代码,play自定义handler里的messageRecived:public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{ Invoker.invoke(new NettyInvokation(request, response, ctx, nettyRequest, e));}...

慈利县15658256602: netty如何使用 -
伯音立迈: 和spring , 先写一个类,然后与一般的bean同样配置 <!-- netty config example --> <bean id="tcpServer" class="com.yixun.collector.server.NettyTCPServer" init-method="createServerBootstrap" destroy-method="stopServer"> <...

慈利县15658256602: 如何像调用本地接口一样调用netty -
伯音立迈: 首先,我们看一下下面这张图片,了解一下通过远程调用接口的过程,从而知道远程调用接口和本地调用的区别,从而能够更好的 根据不同的情况而不同的方式调用EJB.前面我们已经说了怎么开发远程调用的无状态的会话bean,所以现在我...

慈利县15658256602: 如何构建一个基于netty的后端服务器 -
伯音立迈: 下面将分析手头上一个项目,运用的技术很全,值得学习,先做一个简单介绍,当然业务部分代码就不讲了.整个工程采用maven来管理,主要的技术是spring+jedis+netty+disruptor.看这个组合,这个服务器端性能应该很不错.这个工程又引发...

慈利县15658256602: 如何用Netty写一个断开tcp连接的方法 -
伯音立迈: 论一个TCP 连接是如何建立的以及通信结束后是如何终止的.建立一个 TCP 连接TCP使用三次握手 ( three-way handshake ) 协议来建立连接,图 3-10 描述了三次握手的报文序列.这三次握手为:请求端(通常称为客户)发送一个 SYN 报...

慈利县15658256602: netty4 服务器 创建后,使用端口 和ip进行 检测 -
伯音立迈: 1:请检查服务器是否开启了并且内网电脑能成功访问2:检查路由器的端口映射的配置是否正确3:查看自己电脑对应的服务和端口有没甫紶颠咳郯纠奠穴订膜有打开!4:请检查您是否映射了服务器所需的所有端口,有可能没有完全设置访问服务器所需的端口,导致访问失败.您可以通过开启“DMZ主机”来检测一下,是否端口没有映射完全.若开启DMZ主机后,能正常访问服务器,则可能是端口添加不完全.5:检查内网服务器端口是否和远程管理的端口冲突6:服务商可能将相应端口屏蔽导致虚拟服务器无法访问,尝试修改服务端口!

慈利县15658256602: netty 做数据串口传入编码解码可以实现吗 -
伯音立迈: Netty是NIO框架,所以能传字节是必须的,但是传输对象的时候就有了问题,缓冲区里传的还是字节数组,而我们要传一个对象,所以这就需要我们把对象转化为字节数组写入缓冲区传输,接收的时候将字节数组读出并转化为对象,只有这样,自定义的消息才能在客户端与服务器之间传输,当然,传输的消息要实现Serializable接口.

慈利县15658256602: 关于Netty4怎么实现服务发送数据之后等待返回结果 -
伯音立迈: [解决办法] 如果要确定包是一致性的,就用MD5做数据校验. public void operationComplete(ChannelFuture future) { } 这个地方是表示数据已经发送完毕.可以记录一些其他事情,比如日志.发送完毕后,有新数据响应仍然走 Handler原来的流程...

慈利县15658256602: netty通信如何让服务器主动给客户端发送资源 -
伯音立迈: 如果是单纯备份的话,你用备份工具之类的就行了.再说,通常备份的话,都是把数据备份到外部设备才是合理的,你在主机里两块硬盘备份,没什么意义啊.你这种情况,与其说做备份,不如做个RAID1来得好呢.两块磁盘同时写入同样的数据,1块坏掉了,另一块也会继续运转啊.

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网