原创

基于netty自定义二进制协议(hello)

1.协议设计

协议报文由一个通用报文头和实际数据组成
报文头:由魔数,扩展1组成,共5个字节
    魔数(4byte) 、扩展1(1byte)
数据:由数据包指定,可以是文件,也可以是字符串。服务端读完协议头一次读取所有数据

2.协议编码

以websocket为客户端编码实现 核心代码

function sen_pic(){
    //可以是文件,也可以是字符串
    var files = $('#wspic')[0].files;
      if (!files || !files.length) {
        return ;
      }
      //获取后缀
      var ext = getExtCode();
      var file = files[0];
      fileProto(file, ext)  
}
function fileProto(file, ext){
  var fileReader = new FileReader();
  fileReader.readAsArrayBuffer(file);
  fileReader.onload = function (e) {
    var result = e.target.result;

    var extBuffer = new ArrayBuffer(5);
    var dataView = new DataView(extBuffer);
    dataView.setInt32(0, MAGIC_BIN_NUM);
    //1个字节数组缓冲区写扩展类型
    dataView.setInt8(4, ext);

    var blob = new Blob([extBuffer,result]);
    //通过websocket发送二进制数据流
    ws.send(blob);
  }
} 

function getExtCode(){
    var extArr = {jpg:100,jpeg:101,png:102};
    var file=$('#wspic').val(); 
    var filename=file.replace(/.*(\/|\\)/, ""); 
    var fileExt=(/[.]/.exec(filename)) ? /[^.]+$/.exec(filename.toLowerCase()) : '';
    console.log(fileExt[0]);
    var ext = fileExt[0];
    console.log(ext);
    console.log(extArr[ext]);
    return extArr[ext];
 }

3.服务端协议解码

public void binaryWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame){
        BinaryWebSocketFrame msg = (BinaryWebSocketFrame) frame;
        ByteBuf content = msg.content();
        byte[] byteWS = new byte[content.readableBytes()];
        content.readBytes(byteWS);//ByteBuf转字节数组
        //协议头校验
        if(!protocol(content)){ return; }
        //协议文件扩展类型
        byte[] extByte = subBytes(byteWS, 4, 1);
        String ext = byteToExt(extByte);
        byte[] imgByte = subBytes(byteWS, 5, byteWS.length-5);
        //字节流写文件
        WsUtils.writeFile(imgByte, ext);
    }

    /**
     * 协议头
     * @param content
     * @return
     */
    private boolean protocol(ByteBuf content){
        int protocolCode = content.getInt(0);
        System.out.println("protocolCode->"+protocolCode);
        if(protocolCode == MAGIC_BIN_NUM){
            return true;
        }
        return false;
    }

    /**
     * 解析协议头,文件扩展类型
     * @param bytes
     * @return
     */
    public String byteToExt(byte[] bytes) {
        return WsUtils.extCodeToType(bytes[0]);
    }

    /**
     * 截取字节数组
     * @param src
     * @param begin
     * @param count
     * @return
     */
    public byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        System.out.println(src.length+"src");
        for (int i=begin;i<begin+count; i++) bs[i-begin] = src[i];
        return bs;
    }

4.demo

demo源码地址
https://github.com/fireflyi/xiaoqingxin/tree/master/netty-biny-prot

正文到此结束
本文目录