proto协议统计带宽字节流量

我最近在给公司写完游戏底层框架后,公司老板问我目前游戏带宽是多少?在当下流量资源如此充足的环境下我以前还没怎注意过。特地算过游戏带宽后,把遇到的相关问题记录一下。

公司原先使用的是websocket + json。我重写底层后,换成了google protocol

不讨论websocket报文结构,只看有效载荷。 json的带宽绝对是比google protocol的。 我服务器的做法纯粹就是

go 复制代码
var msg = `{"userID":234231233,"pos":{"x":239.2,"y":77.9}}`
user.SendMessage([]byte(msg))

utf-8格式下{"userID":234231233,"pos":{"x":239.2,"y":77.9}}占用47个字节。换成protocol后占字节就下来了

proto 复制代码
syntax = "proto3";

message Move {
  int64 user_id = 1;
  Position pos  = 2;
}

message Position {
  float  x = 1;
  float  y = 2;
}

通过proto解析工具结果来看,使用protocol只占用了17个字节。 写到这里就可以水一篇文章了,不过免得别人说我水。我就再研究一下protocol是怎么做到的,也就是说截图中通过proto解析工具工具解析出来的数据是怎么得到的吧。 先看看官方是怎么说的。

  • tag := (field << 3) bit-or wire_type

    A tag is a combination of a wire_type, stored in the least significant three bits, and the field number that is defined in the .proto file. 我顺便把公式也拿过来了。 公式中还缺少wire_type

ID Name Used For
0 VARINT int32, int64, uint32, uint64, sint32, sint64, bool, enum
1 I64 fixed64, sfixed64, double
2 LEN string, bytes, embedded messages, packed repeated fields
3 SGROUP group start (deprecated)
4 EGROUP group end (deprecated)
5 I32 fixed32, sfixed32, float

那么就可以开始第一步解析了 Move中第一个字段 user_idfield=1.类型是int64,也就是VARINT,ID为0.带入公式

c 复制代码
tag = (1<<3)|0

用计算机算一算可以得到这个值是8

user_id的值是150,二进制数据是 1101 1111 0110 0001 0101 1100 0001

First you drop the MSB from each byte, as this is just there to tell us whether we've reached the end of the number (as you can see, it's set in the first byte as there is more than one byte in the varint). These 7-bit payloads are in little-endian order. Convert to big-endian order, concatenate, and interpret as an unsigned 64-bit integer

官方的说法,我按照7个切割一下。

sh 复制代码
1000001
0101011
1011000
1101111

当后面还有数据时需要在前面补1,得到下面的数据

sh 复制代码
11000001  c1
10101011  ab
11011000  d8
01101111  6f

到现在得到的数据是 08 c1 ab d8 6f

再看看Move第二个字段posfield=2,类型是message也就是LEN,ID为2,带入公署

c 复制代码
tag = (2<<3)|2

用计算机算一算可以得到这个值是18。16进制是12

Position中的两个字段

sh 复制代码
  float  x = 1;
  float  y = 2;

按照相同的方式解析可以得到0d 33 33 6f 4315 cd cc 9b 42。这两个值可以根据IEEE754 float方式计算得到,我就偷个懒了。现在将得到的所有数据拼在一起

08 c1 ab d8 6f 12 0d 33 33 6f 43 15 cd cc 9b 42

会发现少了一个,实际上是LEN类型后面需要跟一个包长,也就是0a 0d 33 33 6f 43 15 cd cc 9b 42数据长度,将这个值补上0A

08 c1 ab d8 6f 12 0a 0d 33 33 6f 43 15 cd cc 9b 42

好了水完了。

对于协议解析感兴趣的可以去tools.ioirb.cn/proto/parse... 这个网站试试看。

相关推荐
十五年专注C++开发13 天前
C++ 序列化 Protocol Buffers:高效数据交换
开发语言·c++·序列化·反序列化·protobuf
喵了几个咪13 天前
统一范式:中后台Admin项目标准化API分层开发方案(Vue/React通用)
前端·vue.js·react.js·protobuf
明月_清风14 天前
二进制序列化入门——为什么二进制比文本更快、更小?
后端·protobuf·messagepack
love530love25 天前
ComfyUI MediaPipe 猴子补丁终极完善版:补全上下文管理与姿态检测兼容
人工智能·windows·python·comfyui·protobuf·mediapipe
Maguyusi1 个月前
Ubuntu26.04 编译 abseil-cpp protobuf v33.6
linux·protobuf·abseil
猫吻鱼1 个月前
【笔记03】【Grpc 和 Protobuf】
grpc·protobuf
xiaodaoluanzha1 个月前
golang中MetaMessage(mm)的使用
json·protobuf
小堃学编程2 个月前
【项目实战】基于protobuf的发布订阅式消息队列(4)—— 服务端
c语言·c++·vscode·消息队列·gtest·protobuf·muduo
遇事不決洛必達2 个月前
某方数据库protobuf详解
爬虫·python·protobuf