Netty之私有协议栈开发

Netty之私有协议栈开发

一.私有协议介绍

    私有协议本质上是厂商内部发展和采用的标准,除非授权,其他厂商一般无权使用该协议。私有协议也称非标准协议,就是未经国际或国家标准化组织采纳或批准,由某个企业自己制定,协议实现细节不愿公开,只在企业自己生产的设备之间使用的协议。

    事实上,私有协议并没有标准定义,只有是能够用于跨进程,跨主机数据交换的非标准协议,都可以称为私有协议,通常情况下,正规的私有协议都有具体的协议规范文档,但是在在实际项目中,内部使用的私有协议往往是口头约定的规范,由于并不需要对外呈现或者被外部调用,所以一般不会单独写相关的内部私有协议规范文档。

 

二.私有协议栈开发

2.1 定义数据结构类NettyMessage实现

package aggrement;

 

importcom.sun.xml.internal.ws.api.message.Header;

 

public class NettyMessage {

        

         privateHeader header;  // 消息头

         privateObject body; // 消息体

        

         publicfinal Header getHeader(){

                   returnheader;

         }

        

         publicfinal void setHeader(Header header) {

                   this.header=header;

         }

        

         publicfinal Object getBody(){

                   returnbody;

         }

   

         publicfinal void setBody(Object body) {

                   this.body=body;

         }

        

        

         publicString toString(){

                   return"NettyMessage [header="+header+"]";

         }

        

}

2.2 消息头Header实现

package aggrement;

 

import java.util.HashMap;

import java.util.Map;

 

public class Header {

        

         privateint crcCode=oxabef0101;

         privateint length;  // 消息长度

         privatelong sessionID;  // 会话ID

         privatebyte type;  // 消息类型

         privatebyte priority;  // 消息优先级

         privateMap<String,Object> attachment=new HashMap<String,Object>();

         publicfinal int getCrcCode() {

                   returncrcCode;

         }

         publicfinal void setCrcCode(int crcCode) {

                   this.crcCode= crcCode;

         }

         publicfinal int getLength() {

                   returnlength;

         }

         publicfinal void setLength(int length) {

                   this.length= length;

         }

         publicfinal  long getSessionID() {

                   returnsessionID;

         }

         publicfinal void setSessionID(long sessionID) {

                   this.sessionID= sessionID;

         }

         publicfinal byte getType() {

                   returntype;

         }

         publicfinal void setType(byte type) {

                   this.type= type;

         }

         publicfinal byte getPriority() {

                   returnpriority;

         }

         publicfinal void setPriority(byte priority) {

                   this.priority= priority;

         }

         publicfinal Map<String, Object> getAttachment() {

                   returnattachment;

         }

         publicfinal void setAttachment(Map<String, Object> attachment) {

                   this.attachment= attachment;

         }

}

    由于心跳消息,握手请求和握手应答消息都可以统一由NettyMessage承载,所以不需要为这几类控制消息做单独的数据结构定义。

2.3 消息编码类NettyMessageEncoder实现

    

package aggrement;

 

import java.io.IOException;

import java.util.List;

import java.util.Map;

 

import io.netty.buffer.ByteBuf;

import io.netty.buffer.Unpooled;

importio.netty.channel.ChannelHandlerContext;

importio.netty.handler.codec.MessageToMessageEncoder;

import io.netty.handler.codec.marshalling.MarshallingEncoder;

/*

 * 消息编码类

 */

public class NettyMessageEncoder extendsMessageToMessageEncoder<NettyMessage>{

        

         MarshallingEncodermarshallingEncoder;

        

         publicNettyMessageEncoder() throws IOException{

                   this.marshallingEncoder=newMarshallingEncoder();

         }

        

         protectedvoid encode(ChannelHandlerContext ctx,NettyMessage msg,List<Object> out)

         throwsException {

                   if(msg==null||msg.getHeader()==null)

                            thrownew Exception("The encode message is null");

                   ByteBuf.sendBuf=Unpooled.buffer();

                   sendBuf.writeInt(msg.getHeader().getCrcCode());

                   sendBuf.writeInt(msg.getHeader().getLength());

                   sendBuf.writeLong(msg.getHeader().getSessionID());

                   sendBuf.writeByte(msg.getHeader().getType());

                   sendBuf.writeByte(msg.getHeader().getPriority());

                   sendBuf.writeInt(msg.getHeader().getAttachment().size());

                   Stringkey=null;

                   byte[]keyArray=null;

                   Objectvalue=null;

                  

                   for(Map.Entry<String,Object>param:msg.getHeader().getAttachment().entrySet()){

                            key=param.getKey();

                            keyArray=key.getBytes("UTF-8");

                            sendBuf.writeInt(keyArray.lenght);

                            sendBuf.writeBytes(keyArray);

                            value=param.getValue();

                            marshallingEncoder.encode(value,sendBuf);

                   }

                   key=null;

                   keyArray=null;

                   value=null;

                   if(msg.getBody()!=null){

                            marshallingEncoder.encode(msg.getBody(),sendBuf);

                   }  else{

                            sendBuf.writeInt(0);

                             sendBuf.senInt(4,sendBuf.readableBytes());

                   }

         }

}

2.4 消息编码工具类MarshallingEncoder实现

package aggrement;

 

import java.io.IOException;

 

import org.jboss.marshalling.Marshaller;

 

import io.netty.buffer.ByteBuf;

import io.netty.channel.ChannelHandlerContext;

importio.netty.handler.codec.marshalling.MarshallingDecoder;

/*

 * 消息编码工具类

 */

public class MarshallingEncoder {

        

         privatestatic final byte[] LENGTH_PLACEHOLDER=new byte[4];

         Marshallermarshaller;

        

         publicMarshallingEncoder() throws IOException{

                   marshaller=MarshallingCodeFactory.buildMarshalling();

                  

         }

        

         protectedvoid encode(Object msg,ByteBuf out) throws Exception{

                   try{

                            intlengthPos=out.writeIndex();

                            out.writeBytes(LENGTH_PLACEHOLDER);

                            ChannelBufferByteOutputoutput=new ChannelBufferByteOutput(out);

                            marshaller.start(output);

                            marshaller.writeObject(msg);

                            marshaller.finish();

                            out.setInt(lengthPos,out.writerIndex()-lengthPos-4);

                   }catch (Exception e) {

                            //TODO: handle exception

                   }finally {

                            marshaller.close();

                   }

                  

                   publicclass NettyMessageDecoder extends LengthFieldBasedFrameDecoder {

                            MarshallingDecodermarshallingDecoder;

                           

                            publicNettyMessageDecoder(int maxFrameLength,int lenthFieldOffset,

                                               intlenthFieldLength) throws IOException {

                                     super(maxFrameLength,lengthFieldOffset,lengthFieldLength);

                                     marshallingDecoder=newMarshallingDecoder();

                            }

                   }

                  

                   protectedObject decode(ChannelHandlerContext ctx,

                                     ByteBufin) throws Exception {

                            ByteBufframe=(ByteBuf) super.decode(ctx,in);

                            if(frame==null){

                                     returnnull;

                            }

                            NettyMessagemessage=new NettyMessage();

                            Headerheader=new Header();

                            header.setCrcCode(in.readerInt());

                            header.setLength(in.readerInt());

                            header.setSessionID(in.readLong());

                            header.setType(in.readByte());

                            header.setPriority(in.readByte());

                           

                            intsize=in.readInt();

                            if(size>0){

                                     Map<String,Object>attach=new HashMap<String,Object>(size);

                                     intkeySize=0;

                                     byte[]keyArray=null;

                                     Stringkey=null;

                                     for(inti=0;i<size;i++){

                                               keySize=in.readInt();

                                               keyArray=newbyte[keySize];

                                               in.readBytes(keyArray);

                                               key=newString(keyArray,"UTF-8");

                                               attach.put(key,marshallingDecoder.decode(in));

                                     }

                                     keyArray=null;

                                     key=null;

                                     header.setAttachment(attach);

                            }

                            keyArray=null;

                            key=null;

                            header.setAttachment(attach);

                   }

                   if(in.readableBytes()>4){

                            message.setBody(marshallingDecoder.decode(in));

                   }

                   message.setHeader(header);

                   returnmessage;

        

         }

}

2.5 消息解码类NettyMessageDecoder实现

package aggrement;

 

import io.netty.buffer.ByteBuf;

importio.netty.channel.ChannelHandlerContext;

importio.netty.handler.codec.LengthFieldBasedFrameDecoder;

 

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

/*

 * 消息解码类

 *LengthFieldBasedFrameDecoder支持自动的TCP粘包和半包处理,只需要给出标识消息长度的字段偏移量

 * 和消息长度自身所占的字节数,netty就能自动实现对半包的处理

 * 对于业务解码器来说,调用父类LengthFieldBasedFrameDecoder的解码方法后,返回的就是整包消息或者为空,

 * 如果为空说明是个半包消息,直接返回继续由I/O线程读取后续的码流

 */

public class NettyMessageDecoder extends

  LengthFieldBasedFrameDecoder{

        

         MarshallingDecodermarshallingDecoder;

        

         publicNettyMessageDecoder(int maxFrameLength,int lengthFieldOffset,

                            intlengthFieldLength) throws IOException{

                  

                   super(maxFrameLength,lengthFieldOffset,lengthFieldLength);

                   marshallingDecoder=newMarshallingDecoder();

         }

        

         @Override

         protectedObject decode(ChannelHandlerContext ctx,ByteBuf in) throws Exception {

                   ByteBufframe=(ByteBuf) super.decode(ctx,in);

                   if(frame==null){

                            returnnull;

                   }

                   NettyMessagemessage=new NettyMessage();

                   Headerheader=new Header();

                   header.setCrcCode(in.readInt));

                   header.setLength(in.readLong());

                   header.setSessionID(in.readLong());

                   header.setType(in.readByte());

                   header.setPriority(in.readByte());

                  

                   intsize=in.readerInt();

                   if(size>0){

                            Map<String,Object>attch=new HashMap<String,Object>(size);

                            intkeySize=0;

                            byte[]keyArray=null;

                            Stringkey=null;

                            for(inti=0;i<size;i++){

                                     keySize=in.readInt();

                                     keyArray=newbyte[keySize];

                                     in.readBytes(keyArray);

                                     key=newString(keyArray,"UTF-8");

                                     attch.put(key,marshallingDecoder.decode(in));

                            }

                            keyArray=null;

                            key=null;

                            header.setAttachment(attch);

                   }

                  

                   if(in.readableBytes()>4){

                            message.setBody(marshallingDecoder.decode(in));

                           

                   }

                   message.setHeader(header);

                   returnmessage;

         }

 

}

2.6 消息解码工具类MarshallingDecoder实现

package aggrement;

 

import io.netty.buffer.ByteBuf;

 

import org.jboss.marshalling.ByteInput;

import org.jboss.marshalling.Unmarshaller;

/*

 * 消息解码工具类

 */

public class MarshallingDecoder {

        

         privatefinal Unmarshaller unmarshaller;

        

   public MarshllingDecoder() throws IOException{

             unmarshller=MarshallerCodeFactory.buildUnMarshalling();

            

    }

   

   protected Object decode(ByteBuf in) throws Exception{

             int ObjectSize=in.readInt();

             ByteBuf buf=in.slice(in.readerIndex(),objectSize);

             ByteInput input=newChannelBufferByteInput(buf);

             try {

                            unmarshaller.start(input);

                            Objectobj=unmarshaller.readObject();

                            unmarshaller.finish();

                            in.readerIndex(in.readerIndex()+objectSize);

                            returnobj;

                   }catch (Exception e) {

                            //TODO: handle exception

                   }finally {

                            unmarshaller.close();

                   }

    }

}

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值