游戏开发中的protobuf自动解码DEMO_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 游戏开发中的protobuf自动解码DEMO

游戏开发中的protobuf自动解码DEMO

 2014/12/30 22:45:30  朋在无锡  程序员俱乐部  我要评论(0)
  • 摘要:本人为游戏服务端开发者,开发中protobuf的解码操作比较麻烦,每次解码都需要写一大堆重复的代码,还需要处理错误,设计了一个工具类,现在将业务逻辑简化一下和出去敏感信息,发布出来,使用源码需要注意以下几点:1.所有protobuf消息基于generatedMessage;2.protobuf运行时需要配置protobuf.exe位置3.反射比较耗费性能,设计中将反射等操作放在系统初始化进行,将结果放置到map中,业务运行时直接取出;.4.开发中结合注解还能进一步简化配置
  • 标签:游戏 开发

本人为游戏服务端开发者,开发中protobuf的解码操作比较麻烦,每次解码都需要写一大堆重复的代码,还需要处理错误,设计了一个工具类,现在将业务逻辑简化一下和出去敏感信息,发布出来,使用源码需要注意以下几点:

1.所有protobuf 消息基于 generatedMessage;

2.protobuf运行时需要配置protobuf.exe位置

3.反射比较耗费性能,设计中将反射等操作放在系统初始化进行,将结果放置到map中,业务运行时直接取出;.

4.开发中结合注解还能进一步简化配置,不需要添加class 到map中

5.对于编码错误,可能为第三方尝试命令码,编码错误统一管理更加方便屏蔽.

解码代码如下:

package code;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import proto.gen.TestProto.MyMsgReq;

import com.google.protobuf.GeneratedMessage;

public class DecordDemo {
	private final static Map<Integer, Method> DECODE_METHODS_MAP = new HashMap<Integer, Method>();// 存储解码方法MAP
	private final static Map<Integer, Class<? extends GeneratedMessage>> DECODE_CLASSES = new HashMap<Integer, Class<? extends GeneratedMessage>>();// 存储类的map
	private final static int MY_MSG_REQ_CMD = 100;

	public static void main(String[] args) throws Exception {
		initDecode();
		MyMsgReq.Builder reqSrc = MyMsgReq.newBuilder().setId(1).setName("mine");
		MyMsgReq req = decode(MY_MSG_REQ_CMD, reqSrc.build().toByteArray());
		System.out.println(req.getId());
		System.out.println(req.getName());
	}

	/**
	 * 初始化 方法,系统启动时即将解码器反射好,业务逻辑时直接从MAP中查询出,解码
	 * */
	public static void initDecode() {
		addDecodeMethod(MY_MSG_REQ_CMD, MyMsgReq.class);
	}

	public static void addDecodeMethod(int cmd, Class<? extends GeneratedMessage> clazz) {
		try {
			Method m = clazz.getMethod("parseFrom", new Class[] { byte[].class });
			if (DECODE_METHODS_MAP.get(cmd) == null) {
				DECODE_METHODS_MAP.put(cmd, m);
			}
			if (DECODE_CLASSES.get(cmd) == null) {
				DECODE_CLASSES.put(cmd, clazz);
			}

		} catch (NoSuchMethodException | SecurityException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 业务中调用
	 * 
	 * @throws Exception
	 * */
	@SuppressWarnings("unchecked")
	public static <T> T decode(int cmd, byte[] data) throws Exception {
		Method decodeMethod = DECODE_METHODS_MAP.get(cmd);
		Class<? extends GeneratedMessage> clazz = DECODE_CLASSES.get(cmd);
		if (decodeMethod == null || clazz == null) {
			throw new Exception("找不到对应解码方法");
		}
		T req;
		try {
			req = (T) decodeMethod.invoke(clazz, new Object[] { data });
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
			throw new Exception("解码异常", e);
		}
		return req;
	}
}
protobuf代码如下:
package proto.gen;

message MyMsgReq {
	required int32 id = 1;
	optional string name = 2; //
}
  • protoDecoe.zip (3.9 MB)
  • 下载次数: 0
发表评论
用户名: 匿名