C# -Unity客户端与服务器端的网络通信

前言

近段时间在做Unity客户端与python服务器之间的网络通信,由于不同语言之间的类型封装不同,不建议直接收发自定义的协议类型字节序列,而是使用json字符串序列进行过渡。
python提供了json模块进行序列化和反序列化,只需要掌握loads操作和dumps操作即可,使用十分简单。
而C#也可以使用Newtonsoft的动态链接库进行json的序列化和反序列化,下面阐述一下使用的注意事项。

下载

链接:https://pan.baidu.com/s/1kM2euOyT-ivXFJixXkQJSA
提取码:iafl

配置

根据Unity的.Net版本选取相应的Newtonsoft.Json.dll文件,放置在Assets/Plugins/目录下即可,在本项目中使用的是net40版本。

使用

序列化

  • 自定义类型可以序列化为Json数组字符串。
    using Newtonsoft.Json;
    // 自定义类型
    public class Protocol{
    	[JsonProperty("a")]
    	int a;
    	[JsonProperty("b")]
    	string b;
    	[JsonProperty("c")]
    	bool c;
    	public Protocol(int a, string b, bool c){
    		this.a = a;
    		this.b = b;
    		this.c = c;
    	}
    }
    // 序列化
    Protocol message = new Protocol(1, "1", true);
    string str = JsonConvert.SerializeObject(message);	// {"a":1, "b":"1", "c":true}
    
  • List集合或者数组可以序列化为Json对象字符串。
    using Newtonsoft.Json;
    // 方法一
    List<object> message = new List<object>();
    message.Add(1);
    message.Add("1");
    message.Add(true);
    string str = JsonConvert.SerializeObject(message);	// [1, "1", true]
    // 方法二:
    object[] message = new object[3];
    message[0] = 1;
    message[1] = "1";
    message[2] = true;
    string str = JsonConvert.SerializeObject(message);	// [1, "1", true]
    

反序列化

  • json对象字符串可以反序列化为相应的自定义类型。
    string str = "{\"a\": 1, \"b\": \"1\", \"c\": true}";
    Protocol message = JsonConvert.DeserializeObject<Protocol>();
    int a = message.a;	// 1
    string b = message.b;	// "1"
    bool c = message.c;	// true
    
    注意:自定义类型中只能有唯一的含参构造函数(参数可以是Json属性集的子集,但是必须保证所有需要反序列化的情况都是该参数列表的子集)或者没有自定义的构造函数(即只使用默认的无参构造函数),否则会抛出异常JsonSerializationException: Unable to find a constructor to use for type ***. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute.
    举个例子,以上的Protocol类型可以不自定义构造函数,或者自定义构造函数的参数列表为(int a, string b, bool c)。如果自定义构造函数的参数列表为(int a, string b)。一旦反序列化的json字符串含有属性c,就会抛出异常;反之,如果反序列的json字符串只含有属性ab抑或两者都有,就不会抛出异常。然而如果Protocol类型含有两个或以上的自定义构造函数,不管什么样的json字符串反序列化时都会抛出异常。
  • json数组字符串可以反序列化为JArray对象。
    string str = "[1, \"1\", true]";
    JArray message = (JArray)JsonConvert.DeserializeObject(str);
    int a = message[0].ToObject<int>();	// 1
    string b = message[1].ToObject<string>();	// "2"
    bool c = message[2].ToObject<bool>();	// true
    

打包项目使用Newtonsoft.Json抛出NotSupportedException异常

目前遇到了一个很奇怪的bug,在Unity上运行项目Newtonsoft.Json可以正常使用,但是项目打包发布后使用就会抛出NotSupportedException异常。
在Building Settings勾选中Development Build复选框,可以在打包项目的日志文件中定位到出错的位置(就是串行化为json字符串的那一行代码)。
在这里插入图片描述
查找了很多论坛博客也没有发现根本的原因所在,值得提及的是有论坛提到由于发布到iOS平台时使用的是IL2CPP模式,需要转换成静态的C++语言,意味着C#的反射无法正常使用。由于Newtonsoft.Json使用了反射,所以会抛出异常。不过我发布的平台是Windows PC,按道理默认打包方式是Mono,应该不会存在这样的问题,不过还是确认一下比较好。于是我就打开了Player Settings…→Player→Other Settings→Configuration,看到Scripting Backend,的确是Mono没错。可是我再往下看一行,发现Api Compatibility Level竟然是.NET Standard 2.0,便茅塞顿开,原来是Unity的.NET版本与Newtonsoft.Json的版本不一致所导致的异常。
所以就回到了开头所说的,必须要保证Newtonsoft.Json和Unity .NET的版本一致性。
C# -Unity客户端与服务器端的网络通信_第1张图片
Unity .NET

你可能感兴趣的:(编程语言,计算机网络)