前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Unity应用架构设计(11)——一个网络层的构建

Unity应用架构设计(11)——一个网络层的构建

作者头像
用户1161731
发布2018-03-28 11:34:47
1.4K0
发布2018-03-28 11:34:47
举报
文章被收录于专栏:木宛城主木宛城主

对于客户端应用程序,免不了和远程服务打交道。设计一个良好的『服务层』能帮我们规范和分离业务代码,提高生产效率。服务层最核心的模块一定是怎样发送请求,虽然Mono提供了很多C#网络请求类,诸如WebClientHttpWebRequest,但考虑到跨平台,这些类不一定适用。不过不用担心,Unity 5.x提供了新的与网络相关类UnityWebRequest用来替代原先的WWW,这是官方推荐的,也是最佳选择。

使用Token进行身份验证

首先我们必须要考虑的是,怎样和Web服务安全的通信。没错,肯定是身份验证(Authentication)。对于像WebClient这些类,它们会提供一个属性,比如Credentials,可以在此属性设置一些身份验证信息,比如用户名,密码,域。这是一个很『重』的解决方案,且不论是否能在Unity中实现,单从密码这个角度,很多游戏根本不需要密码。所以,我们需要一种『轻』量级的身份验证机制,这就是Token,中文翻译叫『令牌』。

Token有两个重要的特点:

  • 代表了唯一的身份验证令牌
  • 具有时效性

第一点我们肯定可以理解,唯一性是身份验证的的基础。那第二点怎么理解呢?其实,Token本质上是一串加密过后的字符串,如果没有时效性,万一被窃取之后,他人很容易进行伪造。所以,易变的Token一定比不变的安全,你需要一个算法来动态生成Token,我提供一个简单的算法:

代码语言:javascript
复制
md5(((day*10) + (month*100) + (last2DigitsofYear)*1000)+userId+deviceId)

同理,你需要在Web服务前加上一个过滤器,一样的算法来验证Token是否一致。

Request Pipeline

Pipeline是管道的意思,管道是相连的,代表了请求的流转。由于UnityWebRequest必须配合StartCoroutine,而StartCoroutine又属于View层的代码,这和分层(详见之前的文章)冲突,MVVM框架需要将业务逻辑从View解耦。一个比较好的解决方案是通过中介的HttpTool来解决,它是一个单例的MonoBehaviour,并且不会随着场景的加载被销毁。

代码语言:javascript
复制
public class HttpTool : Singleton<HttpTool>
{
    // 无法在外界使用构造函数,确保Singleton
    protected HttpTool() { }
}

不管是请求还是响应,本质上是一堆数据的集合,将这些数据封装成对象的形式会更加容易管理,我将请求相关的数据封装成HttpRequest对象:

代码语言:javascript
复制
public class HttpRequest
{
    public string Url { get; set; }
    public HttpMethod Method { get; set; }
    public string Parameters { get; set; }
}

而将从Web服务返回的数据封装成HttpResponse对象:

代码语言:javascript
复制
public class HttpResponse
{
    public bool IsSuccess { get; set; }
    public string Error { get; set; }
    public long StatusCode { get; set; }
    public string Data { get; set; }
}

值得注意的是,对应Http请求,不论Get还是Post都会将参数组装成“field1=value1&field2=value2”格式,不同的是Get请求,参数会跟在Url后,而Post请求则在Request Body里。所以需要一个帮助类,反射要传递的对象属性,拼装返回字符串。

核心的请求交由UnityWebRequest实现,通过yield等待返回的结果:

代码语言:javascript
复制
using (var www = UnityWebRequest.Get(url + parameters))
{
    yield return www.Send();
    var response = new HttpResponse
    {
        IsSuccess = !www.isError, Error = www.error, StatusCode = www.responseCode, Data = www.downloadHandler.text
    };
    onComplete(response);
}

最后再对返回的Json字符串反序列化成对象,值得注意的是,在此我用了内置的JsonUtility类,它并不能直接反序列化一个Json数组 ,而是需要将它包装成一个对象 ,通过集合类型属性的形式间接被反序列化。

至此,一个完整的Request Pipeline 如下图所示:

request_pipeline
request_pipeline

使用策略模式增强RemoteRepository

由于JsonUtility的限制因素多,你可能使用其他第三方的库。又或者不反序列化Json,而是Xml。所以在RemoteRepository中不应该限制死反序列化的代码,更好的想法是通过『策略模式』,交由外部算法来实现。这样的好处是你根本不需要改动RemoteRepository里的代码,这也符合『开闭原则』。

所以,你需要在RemoteRepository定义一个序列化接口:

代码语言:javascript
复制
public ISerializer Serializer { get; set; }

然后,对返回的HttpResponse中的Json反序列化:

代码语言:javascript
复制
Serializer.Deserialize<R>(httpResponse.Data)

真正的对Json序列化器实现了ISerializer接口,以策略的形式存在:

代码语言:javascript
复制
public class SerializerJson:ISerializer
{
    public static readonly SerializerJson Instance=new SerializerJson();
    private SerializerJson()
    {
        
    }
    public string Serialize<T>(T obj, bool readableOutput = false) where T : class, new()
    {
        throw new NotImplementedException();
    }

    public T Deserialize<T>(string json) where T : class, new()
    {
        return JsonUtility.FromJson<T>(json);
    }
}

策略模式在编程领域运用非常广,比如Java或者.NET框架里的集合排序,大量用到策略模式。由程序员指定的算法来最终实现排序。

小结

本文的核心思想就是如何在合理分层结果下构建一个好用的服务层。谈到了如何动态生成Token来实现身份验证,以及分层情况下的请求流程。对于2D并且以数据绑定为基础的游戏,我认为这是一个好的实践方案。因为不管是三层架构还是N层架构,通过分层的好处是更加清晰去实现业务逻辑。 源代码托管在Github上,点击此了解

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 使用Token进行身份验证
  • Request Pipeline
  • 使用策略模式增强RemoteRepository
  • 小结
相关产品与服务
多因子身份认证
多因子身份认证(Multi-factor Authentication Service,MFAS)的目的是建立一个多层次的防御体系,通过结合两种或三种认证因子(基于记忆的/基于持有物的/基于生物特征的认证因子)验证访问者的身份,使系统或资源更加安全。攻击者即使破解单一因子(如口令、人脸),应用的安全依然可以得到保障。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档