基于Netty的网络协议我们在设计的时候一般只考虑一种固定的协议格式很少会考虑到去用多路复用的方式去适配混杂协议的处理,那我们应该如何处理一个端口动态适配不同协议数据的解析处理呢?,这就要考虑到动态装配pipeline了,网上很多资料介绍了netty的pipeline而且说的也很详细,这里我就从多协议适配的思路来具体操作pipeline过程。
首先我们看一下如何做多协议适配下面有如下协议(举例)
| 协议描述 | 协议载体 |
|---|---|
| 协议1 | 主机标识+长度+ 协议内容 |
| 协议2 | 协议长度长度+ 协议内容 |
| 协议3 | 协议长度长度+crc校验+ 协议内容 |
上面的协议我们要通过一个端口来做适配我们就可以增加协议头也就是在dubbo中我们常听过的magic code 这个magic code一方面是做协议传输是否正确判断另外我们可以根据magic code来区分不同的协议,我们可以在协议区分不明显时增加协议连接头来区分不同的协议。
如果我们在基于标准协议上扩展适配其他协议如何做呢?
比如我想通过8096端口实现websocket协议适配和私有TCP协议适配。我们首先分析websocket协议101请求还是基于http协议那么101实际是一个GET请求,HTTP请求前缀有明显的标识比如GET/POST等,我们只需要私有TCP协议的请求头部不和HTTP协议相同就可以做适配。
下面我说明一下如何基于Netty做多协议适配
1、继承ChannelInboundHandlerAdapter 继承ChannelInboundHandlerAdapter主要实现多协议适配。
2、通过pipeline.addLast(new 协议处理器());来动态挂载协议解码器和编码器。
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if(msg instanceof ByteBuf){
ByteBuf byteBuf=(ByteBuf)msg;
if(byteBuf.readableBytes()>=5){
if((byteBuf.getByte(0)== 'G' || byteBuf.getByte(1)== 'E' byteBuf.getByte(2)== 'T' )
){
//挂载HTTP协议处理器
}else if((byteBuf.getByte(0)== 0x1A || byteBuf.getByte(1)== 0x1F){
//挂载私有协议处理器
}else{
//协议错误拒绝连接
}
}
ctx.fireChannelRead(msg);
}