Client 与 Server 的网络通信协议传输使用 google protobuf,服务器端使用的是 Java
一、Protocol Buffers
protobuf 全称 Google Protocol Buffers,是 google 开发的的一套用于数据存储,网络通信时用于协议编解码的工具库。它和 XML 或者 JSON 差不多,也就是把某种数据结构的信息,以某种格式(XML,JSON)保存起来,protobuf 与 XML 和 JSON 不同在于,protobuf 是基于二进制的。主要用于数据存储、传输协议格式等场合。那既然有了 XML 等工具,为什么还要开发 protobuf 呢?主要是因为性能,包括时间开销和空间开销:
1. 时间开销:XML 格式化(序列化)和 XML 解析(反序列化)的时间开销是很大的,在很多时间性能上要求很高的场合,你能做的就是看着 XML 干瞪眼了。
2. 空间开销:熟悉 XML 语法的同学应该知道,XML 格式为了有较好的可读性,引入了一些冗余的文本信息。所以空间开销也不是太好 (应该说是很差,通常需要实际内容好几倍的空间)。
二、服务器端生成的 proto 文件转换成 Java 文件
示例:proto 文件
syntax = "proto3";
option java_package = "com.showly.app.chat.proto";// 生成 Java 文件后的存放路径
option java_outer_classname = "ChatServerProto";
// 聊天内容类型
enum ContentType {
NORMAL = 0; // 普通文本聊天
ANONYMOUS = 1; // 匿名文本聊天 (输入框旁边有个勾选)
}
// 性别
enum GenderType {
SECRET = 0; // 保密
MALE = 1; // 男
FEMALE = 2; // 女
}
// 用户信息
message UserInfo {
int32 uid = 1;
string headPic = 2;
GenderType gender = 3;
bool vip = 4; //Vip
int32 level = 5; // 等级
string nickName = 6; // 昵称
}
// 响应消息的一个头. 每个消息都会带上.
message ResponseHeader {
int32 status = 1; // 状态 非 0 为失败
string msg = 2; // 状态描述
}
// 聊天使用的消息体对象
message ChatInfo {
UserInfo info = 1; // 用户信息
string location = 2; // 用户的位置.
ContentType type = 3; // 消息类型
bytes content = 4; // 消息内容
int64 dt = 5; // 时间戳
}
// cmdId = 1000(客户端传输到服务器端的请求 id)
message LoginRequest {
int32 uid = 1; //uid
string token = 2; // token
}
// cmdId = 1000000(客户端获取服务器端响应 id)
message LoginResponse {
ResponseHeader header = 1;
repeated ChatInfo chats = 2; // 10 条历史记录
bool roomReconn = 3; // 房间重连
}
// cmdId = 1001 切换城市 世界为 "WORLD"
message ChangeCityRequest {string city = 1; // city code}
// cmdId = 1000001
message ChangeCityResponse {
ResponseHeader header = 1;
repeated ChatInfo chats = 2;// 10 条历史记录
}
enum LocationType {
WORLD = 0;// 世界信息
REDBAGROOM = 1; // 红包活动房间
}
// cmdId = 1002
message SendChatMsgRequest {
string location = 1; // 位置
ContentType type = 2; // 消息类型
bytes content = 3; // 消息内容. 以后可能图片什么. 我这里不写死. 客户端给我字节数组.
LocationType locationType = 4 ;// 消息位置
}
// cmdId = 1000002 推送的聊天信息广播协议
message ChatInfoBroadcastResponse {
ResponseHeader header = 1;
ChatInfo chat = 2; // 广播的内容
LocationType locationType = 3 ;// 消息位置
}
// cmdId = 1003 心跳. 不需要发送东西. 告诉服务器还活着
message HeartRequest {
}
// 这里仅服务端使用这个, 客户端按照下行的 id 解析即可.
message DefaultHeaderResponse {ResponseHeader header = 1; // 头}
转换流程:
1、这时需要 protoc 转换工具 (公众号回复 ”protocbuf 转换工具 ”)
2、将 proto 文件放到工具相应的目录 (如图)
3、使用如图命令行进行转换
转换后的 Java 文件为 ChatServerProto(生成的文件代码太长,这里不放出来了)
三、Protocol Buffer 使用
以使用 Netty 网络编程框架 Protocol Buffer 传输为例:
Netty 登录请求 (此协议为客户端与服务端双方规定好的协议)
// cmdId = 1000
message LoginRequest {
int32 uid = 1; //uid
string token = 2; // token
}
项目代码中使用:
ChatServerProto.LoginRequest loginRequest = ChatServerProto.LoginRequest
.newBuilder()
.setUid(Integer.parseInt(I8ShowSharePre.getHomeId(getActivity())))
.setToken(I8ShowSharePre.getToken(getActivity()))
.build();
MessageContent messageContent = new MessageContent(1000, loginRequest.toByteArray());
//nettyChatClient 为 netty 对象
nettyChatClient.sendMessage(messageContent);
以下是个人公众号 (longxuanzhigu),之后发布的文章会同步到该公众号,方便交流学习 Android 知识及分享个人爱好文章: