准备工具:

工具下载地址如下:https://github.com/protocolbuffers/protobuf/releases/tag/v3.6.1,主要使用到的文件有:

protoc.exe工具:通过此工具将从自定义的协议文件(.proto)得到相应(.java)的Java类文件;
对应proto.exe版本的protobuf-java.jar包,用于解析上面得到的.java类,这里我使用的是2.5.0版本的protobuf;
chat_send.proto协议文件,关于proto协议文件的书写语法详细的可以查看:Protobuf语言指南,chat_send.proto内容如下(包名package可以根据当前服务器应用的包名进行修改):

//定义使用的protobuf版本
syntax = "proto2";
//定义所在的protobuf包空间
package ares.logic.msg.proto; //生成的java类所在的包路径
option java_package = "ares.logic.msg.proto";
//生成的java类的类名
option java_outer_classname = "ChatSendMsg"; //声明一个message类
message ChatSend{ //(5)
optional int32 mid = 1; // 消息ID, 非必要
required int64 playerid = 3; // 游戏角色ID 必要
required int32 userid = 4; // 用户ID, 必要
required int32 power = 5; // 角色战力值(如果没有可设置为角色等级)
required int32 channel = 6; //消息频道 必要
required string content = 7; //聊天内容 必要
required string playername = 8; // 游戏昵称 必要
required int32 zeusid = 9; // 区服ID 必要
required string ip = 10; // 当前发言人的IP 必要
optional int32 banned = 11; // 是否禁言

cs_enum.proto协议类型枚举文件,用于列举所有协议数据结构的编号:

syntax = "proto2";
//定义所在的protobuf包空间
package ares.logic.msg.proto; //生成的java类所在的包路径
option java_package = "ares.logic.msg.proto";
//生成的java类的类名
option java_outer_classname = "EnmMsgId"; enum EnmCmdId
{
UNIVERSAL = 0;
ChatSend = 1001;//登录请求协议号
}

将.proto转化为Java类文件的处理脚本,这里其实只是一句命令行指令:

protoc  chat_send.proto --java_out=../src/

这里我根据实际项目目录结构定义了一个转文件的.bat批处理文件:

echo on
call protoc --version call protoc chat_send.proto --java_out=../src/
call protoc cs_enum.proto --java_out=../src/
PAUSE

protobuf数据通信过程:

1.客户端创建数据:

要构建一个protobuf数据,需要通过对应协议文件的数据结构,先通过每个数据类型的newBuilder()方法来创建对应的Builder对象,再对Builder中的属性进行赋值,最后才能使用Builder来build()数据对象

public ChatSend getProtobuf() {
     ChatSend.Builder chatBuilder = ChatSend.newBuilder();
   chatBuilder.setMid(EnmCmdId.ChatSend.getNumber());
chatBuilder.setPlayerid(roleId);
chatBuilder.setBanned(banned);
chatBuilder.setChannel(channel);
chatBuilder.setContent(content);
chatBuilder.setIp(loginIp);
chatBuilder.setPlayername(roleName);
chatBuilder.setPower(level);
chatBuilder.setUserid(userId);
chatBuilder.setZeusid(serverId);
return chatBuilder.build();
}

客户端单独启用一个线程,将请求的消息发送给服务器

private void initThread() {
BlockingThreadPool.createThreads(BlockingThreadPool.SkyEye_CHECKER, 1, new SocketHandler());
} private class SocketHandler implements BlockingThreadPool.Callbacker<SkyEyeMsg> {
private boolean retry;
@Override
public void callback(SkyEyeMsg info) {
byte[] data = info.getProtobuf().toByteArray();
try {
if (socket == null) {
initSocket();
}
byte[] len = intToByteArray(data.length);
socket.getOutputStream().write(HEAD);
socket.getOutputStream().write(len);
socket.getOutputStream().write(data);
} catch (Exception e) {
closeSocket(); //socket重连
if(retry){
SkyEyeChecker.logger.error("ckeckMsg Exception :" + e);
}else{
retry = true;
callback(info);
retry = false;
}
}
} byte[] intToByteArray(int len) {
byte[] data = new byte[4];
data[0] = (byte) (len >> 24);
data[1] = (byte) (len >> 16);
data[2] = (byte) (len >> 8);
data[3] = (byte) len;
return data;
}
}

最新文章

  1. Git 进阶指南(git ssh keys / reset / rebase / alias / tag / submodule )
  2. 在JAVA中如何跳出当前的多重嵌套循环
  3. java 截取pdf
  4. 记32位Oracle客户端登录报12560协议适配器错误的解决办法
  5. UVa230 Borrowers (STL)
  6. C++暂时对象
  7. sql从某不连续的数字中将其分段并找出缺失的数字并分段
  8. zoj 2193 poj 2585 Window Pains
  9. COCOA&#174; PROGRAMMING FOR MAC&#174; OS X (1)- Get Start
  10. CentOS6.5 安装ntopng-1.2.0
  11. 【转】Python3—UnicodeEncodeError &#39;ascii&#39; codec can&#39;t encode characters in position 0-1
  12. zabbix触发器表达式
  13. play framework 笔记
  14. 超简单(两步)-微信怎么实现打开外部浏览器,下载app,打开网页URL
  15. ACM菜鸡退役帖——ACM究竟给了我什么?
  16. SpringBoot系列: SpringBoot 启动慢的问题
  17. Lua 语言基本语法
  18. 测验2: Python基础语法(上) (第4周)
  19. JavaScript遍历对象中所有元素
  20. js 正则函数初级

热门文章

  1. 【洛谷P4145】花神游历各国
  2. MySQL表结构的优化和设计
  3. JAVA后端生成Token(令牌),用于校验客户端,防止重复提交
  4. 对manacher的一点感性理解
  5. Vue(小案例)底部tab栏和顶部title栏的实现
  6. PHP操作cookie
  7. Qt ------ 添加某个功能,比如(QSerialPort)注意事项
  8. https服务器配置部署
  9. 信用评分卡 (part 1 of 7)
  10. docker 基础之网络管理