protobuf编码及网络通信应用(一)

前言

protobuf 优势,网上随便一搜一堆,这里直接略过。。。
这章主要说下protobuf编码规则及网络通信时快速获得协议消息ID(网上一搜基本上反射消息类型)
感觉有了msgid(消息ID也可以是字符串,不过效率比数字还是会低点) 才有灵魂,根据消息ID 及其它字段判定是否为有效消息(特别针对大的消息体),从而作出相应的处理;
废话不说了,开始讲述了

1: 准备

先写个test.proto 文件 如下

syntax = "proto3";

package proto;

//import "common.proto";
// 1000 loginreq
//消息范围自行设置 日常中小型应用到16256(14bit)够用了
enum MSG {
    CH_MSG_BEGIN = 0;
    CH_Login_Req = 1000;
  //  CH_MSG_1001  ----------CH_MSG_1998  //消息自行添加
    CH_MSG_END = 1999 ;

    HC_Login_Rep = 2000;
   // HC_MSG_2001 ----- HC_MSG_2998 //消息自行添加
    HC_MSG_END = 2999 ;
};

message MessageHead {
    uint32 msgid = 1;	//消息ID  MSG
    fixed32 msgmask = 2;  //流水号
}

message MessageHeadNoMask {
    uint32 msgid = 1;//消息ID 
}

//c->h
message MessageLoginReq {
    MessageHead msghead = 1;
    string  accnmae  = 2;
	string  tokenstr = 3;
}
message MessageLoginReq2 {
    MessageHead msghead = 1;
    string  accnmae  = 2;
	string  tokenstr = 3;
	uint32  t4= 4;
	uint32  t5= 5;
	uint32  t6= 6;
	uint32  t7= 7;
	uint32  t8= 8;
	uint32  t9= 9;
	uint32  t10= 10;
	uint32  t1= 11;
	uint32  t12= 12;
	uint32  t13= 13;
	uint32  t14= 14;
	uint32  t15= 15;
	uint32  t16= 16;
	uint32  t17= 17;
	uint32  t18= 18;
	uint32  t19= 19;
	uint32  t20= 20;
	uint32  t21= 21;
	uint32  t22= 22;
	uint32  t23= 23;
	uint32  t24= 24;
	uint32  t25= 25;
	uint32  t26= 26;
	uint32  t27= 27;
	uint32  t28= 28;
	uint32  t29= 29;
	uint32  t30= 30;
	uint32  t31= 31;
	uint32  t32= 32;
	uint32  t33= 33;
}

再把test.proto编译成 test.pb.go (这里以golang为例)
buildprotobuf_go.bat 内容 protoc --go_out=. *.proto
在这里插入图片描述

生成的文件内容如下

// Code generated by protoc-gen-go. DO NOT EDIT.
// source: test.proto

/*
Package proto is a generated protocol buffer package.

It is generated from these files:
	test.proto

It has these top-level messages:
	MessageHead
	MessageHeadNoMask
	MessageLoginReq
	MessageLoginReq2
*/
package proto

import proto1 "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"

// Reference imports to suppress errors if they are not otherwise used.
var _ = proto1.Marshal
var _ = fmt.Errorf
var _ = math.Inf

// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto1.ProtoPackageIsVersion2 // please upgrade the proto package

// import "common.proto";
// 1000 loginreq
// 消息范围自行设置 日常中小型应用到16256够用了
type MSG int32

const (
	MSG_CH_MSG_BEGIN MSG = 0
	MSG_CH_Login_Req MSG = 1000
	//  CH_MSG_1001  ----------CH_MSG_1998  //消息自行添加
	MSG_CH_MSG_END   MSG = 1999
	MSG_HC_Login_Rep MSG = 2000
	// HC_MSG_2001 ----- HC_MSG_2998 //消息自行添加
	MSG_HC_MSG_END MSG = 2999
)

var MSG_name = map[int32]string{
	0:    "CH_MSG_BEGIN",
	1000: "CH_Login_Req",
	1999: "CH_MSG_END",
	2000: "HC_Login_Rep",
	2999: "HC_MSG_END",
}
var MSG_value = map[string]int32{
	"CH_MSG_BEGIN": 0,
	"CH_Login_Req": 1000,
	"CH_MSG_END":   1999,
	"HC_Login_Rep": 2000,
	"HC_MSG_END":   2999,
}

func (x MSG) String() string {
	return proto1.EnumName(MSG_name, int32(x))
}
func (MSG) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

type MessageHead struct {
	Msgid   uint32 `protobuf:"varint,1,opt,name=msgid" json:"msgid,omitempty"`
	Msgmask uint32 `protobuf:"fixed32,2,opt,name=msgmask" json:"msgmask,omitempty"`
}

func (m *MessageHead) Reset()                    { *m = MessageHead{} }
func (m *MessageHead) String() string            { return proto1.CompactTextString(m) }
func (*MessageHead) ProtoMessage()               {}
func (*MessageHead) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }

func (m *MessageHead) GetMsgid() uint32 {
	if m != nil {
		return m.Msgid
	}
	return 0
}

func (m *MessageHead) GetMsgmask() uint32 {
	if m != nil {
		return m.Msgmask
	}
	return 0
}

type MessageHeadNoMask struct {
	Msgid uint32 `protobuf:"varint,1,opt,name=msgid" json:"msgid,omitempty"`
}

func (m *MessageHeadNoMask) Reset()                    { *m = MessageHeadNoMask{} }
func (m *MessageHeadNoMask) String() string            { return proto1.CompactTextString(m) }
func (*MessageHeadNoMask) ProtoMessage()               {}
func (*MessageHeadNoMask) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }

func (m *MessageHeadNoMask) GetMsgid() uint32 {
	if m != nil {
		return m.Msgid
	}
	return 0
}

// c->h
type MessageLoginReq struct {
	Msghead  *MessageHead `protobuf:"bytes,1,opt,name=msghead" json:"msghead,omitempty"`
	Accnmae  string       `protobuf:"bytes,2,opt,name=accnmae" json:"accnmae,omitempty"`
	Tokenstr string       `protobuf:"bytes,3,opt,name=tokenstr" json:"tokenstr,omitempty"`
}

func (m *MessageLoginReq) Reset()                    { *m = MessageLoginReq{} }
func (m *MessageLoginReq) String() string            { return proto1.CompactTextString(m) }
func (*MessageLoginReq) ProtoMessage()               {}
func (*MessageLoginReq) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }

func (m *MessageLoginReq) GetMsghead() *MessageHead {
	if m != nil {
		return m.Msghead
	}
	return nil
}

func (m *MessageLoginReq) GetAccnmae() string {
	if m != nil {
		return m.Accnmae
	}
	return ""
}

func (m *MessageLoginReq) GetTokenstr() string {
	if m != nil {
		return m.Tokenstr
	}
	return ""
}

type MessageLoginReq2 struct {
	Msghead  *MessageHead `protobuf:"bytes,1,opt,name=msghead" json:"msghead,omitempty"`
	Accnmae  string       `protobuf:"bytes,2,opt,name=accnmae" json:"accnmae,omitempty"`
	Tokenstr string       `protobuf:"bytes,3,opt,name=tokenstr" json:"tokenstr,omitempty"`
	T4       uint32       `protobuf:"varint,4,opt,name=t4" json:"t4,omitempty"`
	T5       uint32       `protobuf:"varint,5,opt,name=t5" json:"t5,omitempty"`
	T6       uint32       `protobuf:"varint,6,opt,name=t6" json:"t6,omitempty"`
	T7       uint32       `protobuf:"varint,7,opt,name=t7" json:"t7,omitempty"`
	T8       uint32       `protobuf:"varint,8,opt,name=t8" json:"t8,omitempty"`
	T9       uint32       `protobuf:"varint,9,opt,name=t9" json:"t9,omitempty"`
	T10      uint32       `protobuf:"varint,10,opt,name=t10" json:"t10,omitempty"`
	T1       uint32       `protobuf:"varint,11,opt,name=t1" json:"t1,omitempty"`
	T12      uint32       `protobuf:"varint,12,opt,name=t12" json:"t12,omitempty"`
	T13      uint32       `protobuf:"varint,13,opt,name=t13" json:"t13,omitempty"`
	T14      uint32       `protobuf:"varint,14,opt,name=t14" json:"t14,omitempty"`
	T15      uint32       `protobuf:"varint,15,opt,name=t15" json:"t15,omitempty"`
	T16      uint32       `protobuf:"varint,16,opt,name=t16" json:"t16,omitempty"`
	T17      uint32       `protobuf:"varint,17,opt,name=t17" json:"t17,omitempty"`
	T18      uint32       `protobuf:"varint,18,opt,name=t18" json:"t18,omitempty"`
	T19      uint32       `protobuf:"varint,19,opt,name=t19" json:"t19,omitempty"`
	T20      uint32       `protobuf:"varint,20,opt,name=t20" json:"t20,omitempty"`
	T21      uint32       `protobuf:"varint,21,opt,name=t21" json:"t21,omitempty"`
	T22      uint32       `protobuf:"varint,22,opt,name=t22" json:"t22,omitempty"`
	T23      uint32       `protobuf:"varint,23,opt,name=t23" json:"t23,omitempty"`
	T24      uint32       `protobuf:"varint,24,opt,name=t24" json:"t24,omitempty"`
	T25      uint32       `protobuf:"varint,25,opt,name=t25" json:"t25,omitempty"`
	T26      uint32       `protobuf:"varint,26,opt,name=t26" json:"t26,omitempty"`
	T27      uint32       `protobuf:"varint,27,opt,name=t27" json:"t27,omitempty"`
	T28      uint32       `protobuf:"varint,28,opt,name=t28" json:"t28,omitempty"`
	T29      uint32       `protobuf:"varint,29,opt,name=t29" json:"t29,omitempty"`
	T30      uint32       `protobuf:"varint,30,opt,name=t30" json:"t30,omitempty"`
	T31      uint32       `protobuf:"varint,31,opt,name=t31" json:"t31,omitempty"`
	T32      uint32       `protobuf:"varint,32,opt,name=t32" json:"t32,omitempty"`
	T33      uint32       `protobuf:"varint,33,opt,name=t33" json:"t33,omitempty"`
}

func (m *MessageLoginReq2) Reset()                    { *m = MessageLoginReq2{} }
func (m *MessageLoginReq2) String() string            { return proto1.CompactTextString(m) }
func (*MessageLoginReq2) ProtoMessage()               {}
func (*MessageLoginReq2) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }

func (m *MessageLoginReq2) GetMsghead() *MessageHead {
	if m != nil {
		return m.Msghead
	}
	return nil
}

func (m *MessageLoginReq2) GetAccnmae() string {
	if m != nil {
		return m.Accnmae
	}
	return ""
}

func (m *MessageLoginReq2) GetTokenstr() string {
	if m != nil {
		return m.Tokenstr
	}
	return ""
}

func (m *MessageLoginReq2) GetT4() uint32 {
	if m != nil {
		return m.T4
	}
	return 0
}

func (m *MessageLoginReq2) GetT5() uint32 {
	if m != nil {
		return m.T5
	}
	return 0
}

func (m *MessageLoginReq2) GetT6() uint32 {
	if m != nil {
		return m.T6
	}
	return 0
}

func (m *MessageLoginReq2) GetT7() uint32 {
	if m != nil {
		return m.T7
	}
	return 0
}

func (m *MessageLoginReq2) GetT8() uint32 {
	if m != nil {
		return m.T8
	}
	return 0
}

func (m *MessageLoginReq2) GetT9() uint32 {
	if m != nil {
		return m.T9
	}
	return 0
}

func (m *MessageLoginReq2) GetT10() uint32 {
	if m != nil {
		return m.T10
	}
	return 0
}

func (m *MessageLoginReq2) GetT1() uint32 {
	if m != nil {
		return m.T1
	}
	return 0
}

func (m *MessageLoginReq2) GetT12() uint32 {
	if m != nil {
		return m.T12
	}
	return 0
}

func (m *MessageLoginReq2) GetT13() uint32 {
	if m != nil {
		return m.T13
	}
	return 0
}

func (m *MessageLoginReq2) GetT14() uint32 {
	if m != nil {
		return m.T14
	}
	return 0
}

func (m *MessageLoginReq2) GetT15() uint32 {
	if m != nil {
		return m.T15
	}
	return 0
}

func (m *MessageLoginReq2) GetT16() uint32 {
	if m != nil {
		return m.T16
	}
	return 0
}

func (m *MessageLoginReq2) GetT17() uint32 {
	if m != nil {
		return m.T17
	}
	return 0
}

func (m *MessageLoginReq2) GetT18() uint32 {
	if m != nil {
		return m.T18
	}
	return 0
}

func (m *MessageLoginReq2) GetT19() uint32 {
	if m != nil {
		return m.T19
	}
	return 0
}

func (m *MessageLoginReq2) GetT20() uint32 {
	if m != nil {
		return m.T20
	}
	return 0
}

func (m *MessageLoginReq2) GetT21() uint32 {
	if m != nil {
		return m.T21
	}
	return 0
}

func (m *MessageLoginReq2) GetT22() uint32 {
	if m != nil {
		return m.T22
	}
	return 0
}

func (m *MessageLoginReq2) GetT23() uint32 {
	if m != nil {
		return m.T23
	}
	return 0
}

func (m *MessageLoginReq2) GetT24() uint32 {
	if m != nil {
		return m.T24
	}
	return 0
}

func (m *MessageLoginReq2) GetT25() uint32 {
	if m != nil {
		return m.T25
	}
	return 0
}

func (m *MessageLoginReq2) GetT26() uint32 {
	if m != nil {
		return m.T26
	}
	return 0
}

func (m *MessageLoginReq2) GetT27() uint32 {
	if m != nil {
		return m.T27
	}
	return 0
}

func (m *MessageLoginReq2) GetT28() uint32 {
	if m != nil {
		return m.T28
	}
	return 0
}

func (m *MessageLoginReq2) GetT29() uint32 {
	if m != nil {
		return m.T29
	}
	return 0
}

func (m *MessageLoginReq2) GetT30() uint32 {
	if m != nil {
		return m.T30
	}
	return 0
}

func (m *MessageLoginReq2) GetT31() uint32 {
	if m != nil {
		return m.T31
	}
	return 0
}

func (m *MessageLoginReq2) GetT32() uint32 {
	if m != nil {
		return m.T32
	}
	return 0
}

func (m *MessageLoginReq2) GetT33() uint32 {
	if m != nil {
		return m.T33
	}
	return 0
}

func init() {
	proto1.RegisterType((*MessageHead)(nil), "proto.MessageHead")
	proto1.RegisterType((*MessageHeadNoMask)(nil), "proto.MessageHeadNoMask")
	proto1.RegisterType((*MessageLoginReq)(nil), "proto.MessageLoginReq")
	proto1.RegisterType((*MessageLoginReq2)(nil), "proto.MessageLoginReq2")
	proto1.RegisterEnum("proto.MSG", MSG_name, MSG_value)
}

func init() { proto1.RegisterFile("test.proto", fileDescriptor0) }

var fileDescriptor0 = []byte{
	// 457 bytes of a gzipped FileDescriptorProto
	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0xd2, 0xdd, 0x6e, 0x12, 0x41,
	0x1c, 0x05, 0x70, 0x01, 0x29, 0xed, 0xd0, 0x76, 0x97, 0xb1, 0xda, 0x63, 0xfd, 0x42, 0xae, 0xaa,
	0x31, 0x0d, 0x3b, 0xb3, 0x5f, 0x5c, 0x78, 0x23, 0x36, 0x60, 0x22, 0x5c, 0x6c, 0x1f, 0x80, 0xac,
	0xed, 0x04, 0x1b, 0x02, 0xdb, 0x76, 0xd7, 0x37, 0xf0, 0x9d, 0x7c, 0x0c, 0x7d, 0x0c, 0x1f, 0xc3,
	0xec, 0xfc, 0xe7, 0x4f, 0x1a, 0xe3, 0xb5, 0x57, 0x70, 0x7e, 0x1c, 0x66, 0x4f, 0x36, 0x23, 0x44,
	0x65, 0xca, 0xea, 0xec, 0xe6, 0xae, 0xa8, 0x0a, 0xd9, 0xb6, 0x1f, 0x83, 0xf7, 0xa2, 0x3b, 0x33,
	0x65, 0x99, 0x2f, 0xcd, 0xd4, 0xe4, 0x57, 0xf2, 0x48, 0xb4, 0xd7, 0xe5, 0xf2, 0xfa, 0x0a, 0x8d,
	0x7e, 0xe3, 0xf4, 0x20, 0xa3, 0x20, 0x21, 0x3a, 0xeb, 0x72, 0xb9, 0xce, 0xcb, 0x15, 0x9a, 0xfd,
	0xc6, 0x69, 0x27, 0xe3, 0x38, 0x78, 0x23, 0x7a, 0xf7, 0xfe, 0x3e, 0x2f, 0x66, 0x79, 0xb9, 0xfa,
	0xf7, 0x21, 0x83, 0x6f, 0xc2, 0x73, 0xd5, 0xcf, 0xc5, 0xf2, 0x7a, 0x93, 0x99, 0x5b, 0xf9, 0xce,
	0x9e, 0xfb, 0xd5, 0xe4, 0x54, 0xed, 0x2a, 0x49, 0xe3, 0xce, 0xee, 0x9d, 0x99, 0x71, 0xa5, 0x5e,
	0x91, 0x5f, 0x5e, 0x6e, 0xd6, 0xb9, 0xb1, 0x2b, 0xf6, 0x32, 0x8e, 0xf2, 0x44, 0xec, 0x56, 0xc5,
	0xca, 0x6c, 0xca, 0xea, 0x0e, 0x2d, 0xfb, 0xd3, 0x36, 0x0f, 0xbe, 0xb7, 0x85, 0xff, 0xd7, 0x73,
	0xd5, 0xff, 0x78, 0xb0, 0x3c, 0x14, 0xcd, 0x2a, 0xc4, 0x43, 0xfb, 0x0a, 0x9a, 0x55, 0x68, 0x73,
	0x84, 0xb6, 0xcb, 0x91, 0xcd, 0x31, 0x76, 0x5c, 0x8e, 0x6d, 0x4e, 0xd0, 0x71, 0x39, 0xb1, 0x39,
	0xc5, 0xae, 0xcb, 0xa9, 0xcd, 0x23, 0xec, 0xb9, 0x3c, 0x92, 0xbe, 0x68, 0x55, 0xc1, 0x10, 0xc2,
	0x42, 0xfd, 0xd5, 0x36, 0x02, 0x74, 0x5d, 0x23, 0xa0, 0x86, 0xc2, 0x3e, 0x37, 0x14, 0x89, 0xc6,
	0x01, 0x8b, 0x26, 0x09, 0x71, 0xc8, 0x12, 0x92, 0x44, 0xf0, 0x58, 0x22, 0x92, 0x18, 0x3e, 0x4b,
	0x4c, 0x92, 0xa0, 0xc7, 0x92, 0x90, 0xa4, 0x90, 0x2c, 0x29, 0xc9, 0x08, 0x8f, 0x58, 0x68, 0xb1,
	0x1a, 0xe2, 0xc8, 0x89, 0x1a, 0x92, 0x04, 0x78, 0xcc, 0x42, 0x9b, 0x95, 0xc2, 0x13, 0x16, 0xda,
	0xac, 0x34, 0x8e, 0x59, 0x68, 0xb3, 0x0a, 0x01, 0x16, 0xda, 0xac, 0x22, 0x3c, 0x65, 0xa1, 0xcd,
	0x2a, 0xc6, 0x09, 0x0b, 0x6d, 0x56, 0x09, 0x9e, 0xb1, 0xd0, 0x66, 0x95, 0xe2, 0x39, 0x0b, 0x6d,
	0x56, 0x23, 0xbc, 0x60, 0xa1, 0xcd, 0x7a, 0x88, 0x97, 0x4e, 0x34, 0x6d, 0xd6, 0x01, 0x5e, 0xb1,
	0xd0, 0x66, 0xad, 0xd0, 0x67, 0xa1, 0xcd, 0x5a, 0xe3, 0x35, 0x8b, 0x7e, 0xbb, 0x10, 0xad, 0xd9,
	0xc5, 0x44, 0xfa, 0x62, 0x7f, 0x3c, 0x5d, 0xcc, 0x2e, 0x26, 0x8b, 0x0f, 0xe7, 0x93, 0x4f, 0x73,
	0xff, 0x81, 0xec, 0x59, 0xb1, 0x57, 0x73, 0x91, 0x99, 0x5b, 0xff, 0x77, 0x47, 0x7a, 0x42, 0xb8,
	0xd2, 0xf9, 0xfc, 0xa3, 0xff, 0xd3, 0xab, 0x3b, 0xd3, 0xf1, 0xb6, 0x73, 0xe3, 0xff, 0xf2, 0xea,
	0xce, 0x74, 0xbc, 0xed, 0xfc, 0x38, 0xfe, 0xb2, 0x63, 0x2f, 0xb0, 0xfe, 0x13, 0x00, 0x00, 0xff,
	0xff, 0x6b, 0xe7, 0x32, 0x2a, 0xe4, 0x03, 0x00, 0x00,
}

2:以golang 工程 说明protobuf 编码
随便创建个testprotobuf工程,再创建个proto目录,把test.proto 及生成的test.pb.go 两个文件放进去
在这里插入图片描述
main.go内容如下

package main

import (
	"github.com/golang/protobuf/proto"
	"log"
	pro "testprotobuf/proto"
)

func main() {

	logreq := pro.MessageLoginReq{&pro.MessageHead{uint32(pro.MSG_CH_Login_Req), 0}, "test", "123456"}
	if data, err := proto.Marshal(&logreq); err == nil {
		log.Printf("%#v", data)
	} else {
		log.Printf("error=%v", err)
	}

	logreq1 := new(pro.MessageLoginReq)
	tdata := []byte{0xa, 0x3, 0x8, 0xe8, 0x7, 0x12, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1a, 0x6, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36}
	if err2 := proto.Unmarshal(tdata, logreq1); err2 == nil {
		log.Printf("%#v", logreq1)
	} else {
		log.Printf("Unmarshal error=%v", err2)
	}

	login2 := new(pro.MessageLoginReq2)
	login2.Msghead = &pro.MessageHead{uint32(pro.MSG_CH_Login_Req), 0}
	login2.T33 = 1
	if data, err := proto.Marshal(login2); err == nil {
		log.Printf("%#v", data) //[]byte{0xa, 0x3, 0x8, 0xe8, 0x7, 0x88, 0x2, 0x1}
	} else {
		log.Printf("error=%v", err)
	}

	log.Printf("end")
}

运行后
logreq := pro.MessageLoginReq{&pro.MessageHead{uint32(pro.MSG_CH_Login_Req), 0}, “test”, “123456”} 对应
[]byte{0xa, 0x3, 0x8, 0xe8, 0x7, 0x12, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1a, 0x6, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36}

login2 := new(pro.MessageLoginReq2)
login2.Msghead = &pro.MessageHead{uint32(pro.MSG_CH_Login_Req), 0}
login2.T33 = 1 对应
[]byte{0xa, 0x3, 0x8, 0xe8, 0x7, 0x88, 0x2, 0x1}

在这里插入图片描述

先来个protobuf 编码图
可用的wire类型如下:(下面图片为网上找的)
网上找的
下面详细分析编码

......
message MessageHead {  //0x8, 0xe8, 0x7,
    uint32 msgid = 1;	 1000  1<<3+0 =8 =0x8  内容 1000  2进制 111    1101000(高到低)
	Varint 表示1(有后续)+7bit再加高位一字节  0(无后续)+7bit   = 1  1101000  0 0000111 (低到高)0xE8 0x7
    fixed32 msgmask = 2;  默认值0 不需编码
}

logreq := pro.MessageLoginReq{&pro.MessageHead{uint32(pro.MSG_CG_Login_Req), 0}, "test", "123456"} 
[]byte{0xa, 0x3, 0x8, 0xe8, 0x7, 0x12, 0x4, 0x74, 0x65, 0x73, 0x74, 0x1a, 0x6, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36}

message MessageLoginReq { //序号 field_number 类型 wire类型表对照 一般 field_number<<3+wire类型  Varint类型
    MessageHead msghead = 1;  1<<3+2= 10 =0xa  因为类型是2 后面是长度 0x3 表示 MessageHead 只有3个字节
    string  accnmae  = 2;  2<<3+2 = 16 = 0x12 因为类型是2 后面是长度 0x4  内容 0x74, 0x65, 0x73, 0x74
	string  tokenstr = 3;  3<<3+2 = 24+2=26=0x1a string 长度   0x6  内容为 0x31, 0x32, 0x33, 0x34, 0x35, 0x36
}

[]byte{0xa, 0x3, 0x8, 0xe8, 0x7, 0x88, 0x2, 0x1}
message MessageLoginReq2 {
    MessageHead msghead = 1;  //跟上个一样解析
    string  accnmae  = 2;     //默认值 "" 无需编码
	string  tokenstr = 3;     //默认值 "" 无需编码
	...
	//对应0x88, 0x2, 0x1     10001000   00000010    00000001
	uint32  t33= 33; 值为1  33<<3+0 =264 =0x108 = 10 0001000(一共9个bit) 
	超过7bit , 一个字节表示不全,Varint 类型 最高位补1  
	那么就是 1(后续有数据)+ 0001000(现有的低7bit) = 1 0001000   = 0x88 再加
    下个高位字节 0(后续没数据)+ 中间补50 +         10(剩余的2 bit) =0x2
    数据内容一样 是 Varint    1
}

field_number<<3+wire类型 数字 Varint 类型(是否有后续+7bit)
Varint 看高位是否为1 决定后面是否有后续数据
Length-delimited 后面跟着长度 长度类型为 Varint
Start group End group 已经不用了
64-bit 固定 64bit 8个字节
32-bit 固定 32bit 4个字节

编码规则
field_number <<3+ 类型 +长度(Length-delimited 类型时有效)+ 内容
所以上叙的网络消息解析,可以用下面类试函数获得msgid 然后 switch msgid {case …}
久违的 switch case 可以用了 (c/c++ java js 等自行修改)
注意的最短的消息长度,函数里没作判定

func GetProtoMsgID(data []byte) uint32 {
	var sMsgID uint16 = uint16(uint8(data[3] & 0x7f))
	if (uint8(data[3]) & 0x80) > 0 {
		sMsgID += (uint16(data[4]) & 0x7f) << 7
	}
	return uint32(sMsgID)
}

func GetProtoMsgIdAndMask(data []byte) (uint32, uint32) {
	var sMsgID uint16 = uint16(uint8(data[3] & 0x7f))
	var maskindex uint16 = 5
	if (uint8(data[3]) & 0x80) > 0 {
		sMsgID += (uint16(data[4]) & 0x7f) << 7
		maskindex += 1
	}

	var sMaskID uint32 = uint32(data[maskindex])
	sMaskID |= uint32(data[maskindex+1]) << 8
	sMaskID |= uint32(data[maskindex+2]) << 16
	sMaskID |= uint32(data[maskindex+3]) << 24

	return uint32(sMsgID), sMaskID
}

3: 写这章主要为了后面自己忘了,好检回来
最后推荐个更快的 Cap’n Proto ,不过支持的编程语言比protobuf 少点,常用的应该都是支持的
https://capnproto.org/otherlang.html 自行了解,哈哈,前人栽树后人乘凉

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值