Unity使用Protocolbuf通信中遇到的问题

517 阅读3分钟

protocolbuf和Unity的兼容问题

   Protocolbuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持php、java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作,所以在市面上应用非常广泛。
  但是Protobuf是基于.net2.0框架的,而Unity是默认使用.net2.0 Subset框架,如下图:

  若不做任何处理,直接在Unity中使用Protocolbuf进行通信,则会产生类似如下的错误:
  而解决方法也非常简单,主需要将PlayerSetting中Api Compatibility Level 设置成.Net 2.0即可,如下图所示:

C#和Java通信的问题

  网络协议规定低内存地址存放高字节,高内存地址存放低字节。不同处理器处理字节的方式各有不同,C#以小端方式处理字节序列,发送字节数组,即低内存地址存放低字节,高内存地址存放高字节。而Java虚拟机则以大端的顺序来存放。即低内存地址存放高字节,高内存地址存放低字节。
  比如有一个int 数为 129,其转换为字节数组为{129,0,0,0},一个大小为4的字节数组,C#对应的二进制为 00000000 00000000 00000000 10000001,十进制为129,而对于Java虚拟机,则会把上述字节数组翻译为“大端”,对应的二进制为 10000001 00000000 00000000 00000000. 由于Java没有无符号数,最高位代表符号位,这里的二进制最高位为1,代表负数,而Java虚拟机用补码表示负数,所以此数的绝对值代表的二进制为:01111111 00000000 00000000 00000000.加上符号,转换为十进制为-2130706432。
  于是,如果没有对大小端进行统一,就会出现发送方的数据与接收方的数据不一致的问题。C#发送129,Java收到的却是-2130706432。
  解决办法是:需要在客户端进行转换,可以用 IPAddress.HostToNetworkOrder把需要发送的字节序列转换为网络字节序列,即转换为大端序列。由于Java虚拟机采用的就是大端序列,所以服务端不需要进行处理。C#端处理代码如下:

int testInt = 129;
byte[] ints = System.BitConverter.GetBytes(IPAddress.HostToNetworkOrder(testInt));