使用Protobuf定义网络协议

准备工具:

工具下载地址如下: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;
		}
	}

 

转载于:https://www.cnblogs.com/cherish010/p/9871291.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
protobufProtocol Buffers)是一种用于序列化结构化数据的语言无关、平台无关、可扩展的机制。它可以用于网络消息协议的设计。下面将介绍protobuf作为网络消息协议的优点。 首先,protobuf具有良好的性能。相比于其他序列化机制,protobuf具有更高的效率和更小的数据体积。因为protobuf使用二进制编码,并且采用紧凑的数据格式,所以在网络传输过程中能够更快地进行数据传输,减少带宽占用和网络资源消耗。 其次,protobuf具有良好的跨语言支持。因为protobuf使用IDL(Interface Definition Language)来定义消息结构,它能够生成多种语言的代码,包括C++, Java, Python等。这样,不同语言的服务端和客户端可以通过protobuf定义的消息结构进行通信,实现跨平台、跨语言的消息传递。 此外,protobuf还具有可扩展性。当需求变化时,可以很方便地通过更新消息结构来支持新的数据类型或字段,而无需改变底层的网络通信协议。 protobuf支持向后和向前兼容,可以确保客户端和服务端的平滑升级。 另外,protobuf还支持消息的压缩和加密,以提高数据传输的安全性和效率。通过使用压缩算法和加密算法,可以减少消息的大小,并保护数据的机密性。 综上所述,protobuf作为网络消息协议具有较高的性能、良好的跨语言支持、可扩展性和安全性等优点。因此,使用protobuf作为网络消息协议可以提高数据传输的效率和安全性,并实现跨平台、跨语言的消息通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值