私有协议本质上是厂商内部发展和采用的标准,除非授权,其他厂商一般无权使用该协议。私有协议也称非标准协议,就是未经国际或国家标准化组织采纳或批准,由某个企业自己制定,协议实现细节不愿公开,只在企业自己生产的设备之间使用的协议。
事实上,私有协议并没有标准定义,只有是能够用于跨进程,跨主机数据交换的非标准协议,都可以称为私有协议,通常情况下,正规的私有协议都有具体的协议规范文档,但是在在实际项目中,内部使用的私有协议往往是口头约定的规范,由于并不需要对外呈现或者被外部调用,所以一般不会单独写相关的内部私有协议规范文档。
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+"]";
}
}
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
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
returnattachment;
}
publicfinal void setAttachment(Map
this.attachment= attachment;
}
}
由于心跳消息,握手请求和握手应答消息都可以统一由NettyMessage承载,所以不需要为这几类控制消息做单独的数据结构定义。
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
MarshallingEncodermarshallingEncoder;
publicNettyMessageEncoder() throws IOException{
this.marshallingEncoder=newMarshallingEncoder();
}
protectedvoid encode(ChannelHandlerContext ctx,NettyMessage msg,List
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
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());
}
}
}
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
intkeySize=0;
byte[]keyArray=null;
Stringkey=null;
for(inti=0;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; } } 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 intkeySize=0; byte[]keyArray=null; Stringkey=null; for(inti=0;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; } } 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(); } } } 2.5 消息解码类NettyMessageDecoder实现
2.6 消息解码工具类MarshallingDecoder实现