我们的游戏项目中使用了protobuf协议,但是由于协议优化了的缘故,当服务器发送字段值等于0 的时候,客户端协议解析出来后看不到这个值为0零的字段,但是如果直接用“.“去访问是可以访问的。于是问题就来了当我们数据需要更新的时候,如果在lua中 直接 for in pairs 去获得解析到的数据的键值,如果这个键的值是0 的话那么那么将会获取不到,也就是说这个时候无法判断这个字段是否是 0 ,还是根本服务器就没有发送过来。
于是我们就使用看 按位与的方式去检测和判断 服务器是否发了这个字段,对此,如果是需要更新的协议服务器都要多发一个mask 字段 这是一个 二进制转换后的十进制数,协议字段按照顺序,如果发了,,则这个位置为1,否则为0,如协议:
//申请入帮 message C2GSApplyJoinOrg { optional uint32 orgid = 1; optional uint32 flag = 2; }
如果服务器发送了 orgid = 10 , flag = 0 过来,那么客户端只能看到 orgid = 10 这个字段,而看不到 flag 这个。
所以在客户端中我们就做了如下处理:
--dOri 是服务发送过来经过客户端解析后的数据 function CNetCtrl.DecodeMaskData(self, dOri) local d = {} local lKey = {"orgid","flag"} if lKey then local iMask = dOri.mask --服务发送时带一个二进制的mask字段 if iMask then local right = 1 for i=1, #lKey do right = right * 2 if MathBit.andOp(iMask, right) ~= 0 then local key = lKey[i] d[key] = dOri[key] end end -- table.print(d, "CNetCtrl解析mask: "..sType) return d end end return dOri end function MathBit.__base(left, right, op) if left < right then left, right = right, left end local res = 0 local shift = 1 while left ~= 0 do local ra = left % 2 local rb = right % 2 res = shift * op(ra,rb) + res shift = shift * 2 left = math.modf( left / 2) --相当于右移一位 right = math.modf( right / 2) end return res end function MathBit.andOp(left, right) return MathBit.__base(left, right, MathBit.__andBit) end function MathBit.__andBit(left,right) --按位相与 return (left == 1 and right == 1) and 1 or 0 end
这样处理完成之后的数据 客户端就是可以打印出来查看了。并且可以直接使用for in pairs 去打印他们为0的值。