文档章节

我的Protobuf消息设计原则(续)--实践

newzai
 newzai
发布于 2014/07/19 23:49
字数 1429
阅读 10211
收藏 122

1.首先为 聊天服务器(Chat)定义google protobuf的协议接口文件

接口主要遵循 Request、Response、Notification(Indication),Command(本文未出现)四大消息分类,并且使用Message顶层消息把Request、Response,Notification等包含起来;并定义一个MSG枚举值,用于表示具体的消息值(在google protobuf RPC过程中,其实 每个service方法就是一个Request和Response的应答对,只不过其消息值的编码是RPC自动分配的)

package chat; //定义protobuf的包名称空间,对应C++,C#的nanmespace,Java的package
enum MSG
{
 Login_Request  = 10001;
 Login_Response  = 10002;
 Logout_Request  = 10003;
 Logout_Response  = 10004;
 Keepalive_Request = 10005;
 Keepalive_Response = 10006;
 Get_Friends_Request = 10007;
 Get_Friends_Response = 10008;
 Send_Message_Request = 10009;
 Send_Message_Response = 10010;
 Friend_Notification = 20001;
 Message_Notification = 20002;
 Welcome_Notification = 20003;
}
/*下面定义具体的消息内容,MSG枚举中的每个消息ID,如果有消息体,则会对应一个message 定义,如果无消息体则不必要*/ 
/*Login_Request 消息ID对应的消息名称为LoginRequest ; 规则为取掉下划线,有利于某些自动化编码工具编写自动化代码*/ 
message LoginRequest
{
 required bytes username = 1;
 optional string password = 2;
}
message LoginResponse
{
 required fixed32 ttl = 1;
}
/*没有对应的MSG id,则为其它 消息的字段,作为子消息,可以消息嵌套定义,也可以放在外面,个人习惯放在外部。*/ 
message Friend
{
 required bytes name  = 1;
 optional bool  online = 2;
}
message GetFriendsResponse
{
 repeated Friend  friends  = 1;
}
message SendMessageRequest
{
 optional bytes receiver = 1;
 required bytes  text  = 2;
}
message FriendNotification
{
 required bytes name  = 1;
 optional bool online = 2;
}
message MessageNotification
{
 required bytes sender = 1;
 required bytes text = 2;
 required string timestamp = 3;
}
message WelcomeNotification
{
 required  bytes text = 1;
}
/*请求消息集合,把所有的 XxxxxRequest消息全部集合在一起,使用起来类似于C语言的联合体,全部使用optional字段,任何时刻根据MSG 的id值,最多只有一个有效性, 从程序的逻辑上去保证,编译器(不管是protoc还是具体语言的编译器都无法保证)*/ 
message Request
{
 optional LoginRequest login = 1;
 optional SendMessageRequest send_message = 2;
}
/*与Request作用相同,把所有的XxxxResponse消息集合在一起,当作联合体使用,不过额外多了几个字段用于表示应答的结果*/ 
message Response
{
 required bool result = 1;  //true表示应答成功,false表示应答失败
 required bool last_response = 2;// 一个请求可以包含多个应答,用于指示是否为最后一个应答
 optional bytes error_describe = 3;// result == false时,用于描述错误信息
 optional LoginResponse login = 4;
 optional GetFriendsResponse get_friends = 5;
}
/*与Request相同,把所有的XxxxxNotification消息集合在一起当作联合体使用.*/ 
message Notification 
{
 optional FriendNotification friend = 1;
 optional MessageNotification msg = 2;
 optional WelcomeNotification welcome = 3;
}
/*顶层消息,包含所有的Request,Response,Notification,具体包含哪个消息又 MSG msg_type字段决定,程序逻辑去保证msg_type和具体的消息进行匹配*/ 
message Message 
{
 required MSG  msg_type = 1;
 required fixed32 sequence = 2;//消息系列号,主要用于Request和Response,Response的值必须和Request相同,使得发送端可以进行事务匹配处理
 optional fixed32 session_id = 3;
 optional Request request  = 4;
 optional Response response = 5;
 optional Notification notification = 6;
}

2.工程实例

服务器和客户端均使用C#语言开发,主要是考虑到Net集成的网络框架使用起来比较方面,做实例工程比较快;

google protobuf官方的第三方支持库下载protobuf的NET版本

具体工程文件可以从此下载: http://download.csdn.net/detail/chenxiaohong3905/7654087

通信模式采用TCP,在protobuf的二进制基础上追加了 4个字节的包头,用于表示protobuf 二进制数据的长度(不包含4字节自身)

3. wireshard 抓包分析

普通的wireshark版本是不支持protobuf抓包解析的,可以下载http://download.csdn.net/detail/chenxiaohong3905/7244655 版本(需要10 CSDN积分,后面要取消,无法取消积分,上传新的文件也没资格了)

安装完下载的版本后需要对齐进行配置 在wireshark安装目录下有个protobuf的文件夹用于存放所有 要解析的protobuf文件和配置;

注意事项: 每一个端口只能对应一个顶层消息 ,至于为何每个端口只能有一个顶层消息可以去cnblog参考陈硕的文章,里面关于protobuf的描述已经解释了这个问题; protobuf 文件可以包含其它protobuf接口文件,会自动加载,配置的时候只需要指定顶层消息所在的proto文件即可;

里面vcs.conf是一个配置实例

对于 聊天服务器的配置可以如下:

把 protocol.proto文件复制为 wireshark/protobuf文件夹下面,并穿件一个 文件 protocol.conf 输入一下内容即可

# same config file for parsing Message messages

name                  = Message

proto_file            = protocol.proto

port                  = 39999

  name 为顶层消息的名称, port为源或目标的端口之一,不管是TCP,UDP都会尝试解析;如果port端口有其它协议优先注册了,则无法解析为protobuf,需要手动解析;

3.1 连接建立 , 服务器推送 Welcome_Notification消息到客户端

  此流程非必须,只不过为抓包而演示

GoogleProtocolBuffer , Length 59 描述了 Message 消息二进制的总长度

3.2 登录聊天服务器

3.3. 获取朋友列表

 简单的推送服务器的所有已经登录的用户,包含当前用户

3.4 用户通知

 当用户登录或者注销时通过其它用户

3.5 发送消息与消息推送

只演示发送广播消息,所有用户都会接收到包含自己

3.6 注销

© 著作权归作者所有

newzai
粉丝 65
博文 10
码字总数 10368
作品 1
深圳
高级程序员
私信 提问
加载中

评论(19)

纯洁的坏蛋
纯洁的坏蛋
多谢 多谢 我正在学习服务器编程 准备用netty
newzai
newzai 博主

引用来自“lizhenmxcz”的评论

你好,请教个问题,为什么顶层消息生成的C++类中没有设置自定义成员的方法呢,比如set_XXX

有的,你仔细看,set_msg_type,等都有
l
lizhenmxcz
你好,请教个问题,为什么顶层消息生成的C++类中没有设置自定义成员的方法呢,比如set_XXX
newzai
newzai 博主

引用来自“hexleo”的评论

如何实现消息加密?Protobuf自带加密?

zlib压缩,至于加密应该是呀自定义
大海月升
大海月升
如何实现消息加密?Protobuf自带加密?
newzai
newzai 博主

引用来自“BoXuan”的评论

还是自定义协议好用,用这个序列化,还要加些多余的属性名,我只想要能用的纯数据
等你以后体会到了,你就知道了。
kakai
kakai
还是自定义协议好用,用这个序列化,还要加些多余的属性名,我只想要能用的纯数据
newzai
newzai 博主

引用来自“Terryang”的评论

资源分搞个10分,为了赚积分?还是推广?1
这个是很早之前上传的,我积分很多;后面在上传替换不掉有,也修改不了积分; win32( 微云):http://url.cn/RRxS8y win64(微云):http://url.cn/KNXdCi
newzai
newzai 博主

引用来自“banshan2”的评论

没有csdn积分,希望大侠可以上传到网盘里。
win32( 微云):http://url.cn/RRxS8y win64(微云):http://url.cn/KNXdCi
Terryang
Terryang
资源分搞个10分,为了赚积分?还是推广?1
protobuf,json,xml,binary,Thrift之间的对比

golang 使用 protobuf 的教程 golang使用protobuf 一条消息数据,用protobuf序列化后的大小是json的10分之一,xml格式的20分之一,是二进制序列化的10分之一,总体看来ProtoBuf的优势还是很明...

mickelfeng
2018/11/19
447
0
我的Protobuf消息设计原则

网络通信涉及到消息的定义,不管是使用二进制模式、xml、json等格式。消息都可以大体的分为 命令消息、请求消息、应答消息和指示消息4大消息类型。一般情况下每个消息还还有包含一个序列号和...

newzai
2013/09/04
21.9K
48
Google Protobuf 开发指南

Google Protobuf开发指南 1.简介 l 它是开源项目:http://code.google.com/p/protobuf/ l 由google开发,并且在google内部使用 l Protobuf的作用和xml、json是一回事,但他是二进制格式,性能...

macwe
2013/08/29
16K
1
android使用protobuf实现网络订单管理功能

在新版本的Beetle.NetPackage开源组件中集成了对Protobuf的支持,在android下可以简单地使用Beetle.NetPackage实现基于Protobuf的TCP通讯数据交互.下详细讲解实现一个网络订单管理功能的过程....

泥水佬
2013/09/08
3.3K
0
在网络通讯中应用Protobuf

Protobuf的设计非常适用于在网络通讯中的数据载体,它序列化出来的数据量少再加上以K-V的方式来存储数据,对消息的版本兼容性非常强;还有一个比较大的优点就是有着很多的语言平台支持。下面...

泥水佬
2013/08/28
7.5K
16

没有更多内容

加载失败,请刷新页面

加载更多

CSS3 : transition 属性

本文转载于:专业的前端网站➧CSS3 : transition 属性 CSS3的 transition 属性用于状态过度效果! 1、语法: 1 transition: property duration timing-function delay;2 -moz-transition: ...

前端老手
34分钟前
6
0
一个简单的加密工具,性能貌似不行,待优化

一个简单的加密工具,性能貌似不行,待优化 package com.kxvz.common.crypt;import javax.crypto.Cipher;import javax.crypto.KeyGenerator;import javax.crypto.SecretKey;import java.i......

Kxvz
37分钟前
5
0
vue实现路由懒加载

一、为什么要实现懒加载 减少首屏加载时间,避免白屏 二、常用的懒加载方式有两种:即使用vue异步组件 和 ES中的import a、vue异步加载: import Vue from 'vue' import Router from 'vue-ro...

Bing309
39分钟前
7
0
axios拦截器

axios.interceptors.response.use(response => { if (response.data.code == 0) { return response.data } else if (response.data.code == 600) { Cookies.remove('Admin-Token') router.pu......

Cyoya
42分钟前
6
0
给大家分享下部署云桌面的几个小技巧

从去年4月份开始我们公司就开始使用云桌面来进行上网办公的,在这一年多的使用过程中并没有出现像网上和有些用户说的那样,说云桌面各种坑老是出现这样和那样的问题,而我们之所以用的还不错...

GZASD
42分钟前
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部