U3D客户端框架之实现基于UnityWebRequest的Http服务 实现HttpCallBackArgs参数类HttpRoutine访问器HttpManager管理器
Posted 天才小熊猫oo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了U3D客户端框架之实现基于UnityWebRequest的Http服务 实现HttpCallBackArgs参数类HttpRoutine访问器HttpManager管理器相关的知识,希望对你有一定的参考价值。
1 Http服务 访问器设计思路
Unity3D 在2018版本中弃用了WWW请求,使用UnityWebRequest 进行网络请求,这个方法是为了满足今天的 HTTP 通信的需求,而且诞生的新类,相对于WWW这个方法,会更灵活一些,但是用起来却很不方便。
所以我将UnityWebRequest封装了一下。封装的目的有两个:1.封装后访问Http用着方便;2.在框架层上隔离原生API和具体业务,即使后续API变更也不会影响到业务逻辑,避免业务受影响。
2 代码实现
Get和Post的区别可以看 引用模块中 Get和Post对比的链接,那篇文章中详细讲解了Get和Post的异同和使用场景。
HttpCallBackArgs:Http请求的回调数据,包装了是否有错、返回值、数据Bytes数组;说明一下HttpCallBackArgs继承EventArgs,是为了准守规范,让看代码的人一看到这个类型,就知道这是一个事件类型,使用的时候直接吧EventArgs转换成具体的事件参数类即可。
HttpCallBackArgs.cs 代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Myh
//http请求的回调数据
public class HttpCallBackArgs : EventArgs
//是否有错(是否发生了错误)
public bool HasError;
//返回值
public string Value;
//字节数据
public byte[] Data;
HttpRoutine:Http访问Url的轮询器,核心代码的所在文件;内部实现了GetUrl、PostUrl,状态监测、回调处理、对失败情况下的重试逻辑
HttpRoutine.cs 代码实现
using LitJson;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
using YouYou;
namespace Myh
//Http发送数据的回调委托
public delegate void HttpSendDataCallBack(HttpCallBackArgs args);
//Http访问器
public class HttpRoutine
//Http请求回调
private HttpSendDataCallBack m_CallBack;
//Http请求回调数据
private HttpCallBackArgs m_CallBackArgs;
//是否繁忙
public bool IsBusy
get;
private set;
//当前重试次数(尝试重新访问次数?)
public int m_CurrRetry = 0;
//URL
private string m_Url;
//是否是Get
private bool m_IsGetData = false;
//是否是Post
private bool m_IsPost = false;
//发送的数据
private Dictionary<string, object> m_Dic;
public HttpRoutine()
m_CallBackArgs = new HttpCallBackArgs();
#region SendData 发送Web数据
public void SendData(string url, HttpSendDataCallBack cb, bool isPost = false,
bool isGetData = false, Dictionary<string, object> dic = null)
if (IsBusy)
return;
m_Url = url;
m_CallBack = cb;
m_IsPost = isPost;
m_IsGetData = isGetData;
m_Dic = dic;
SendData();
private void SendData()
//不是post模式
if (!m_IsPost)
GetUrl(m_Url);
else
//把数据存到字典里
if (m_Dic != null)
//设备唯一Id
m_Dic["deviceIdentifier"] = DeviceUtil.DeviceIdentifier;
//设备型号
m_Dic["deviceModel"] = DeviceUtil.DeviceModel;
//服务器时间 TODO:
//还没有和服务器同步时间,暂时先用本地时间
long t = DateTime.Now.Ticks;
//用当前服务器时间 和 设备id 算一个md5出来 作为本地请求的签名(签名具有时效性,超时无效)
string md5 = string.Format("0:1",t,DeviceUtil.DeviceIdentifier);
m_Dic["sign"] = EncryptUtil.Md5(md5);
//时间戳
m_Dic["t"] = t;
string json = string.Empty;
if (m_Dic != null)
json = JsonMapper.ToJson(m_Dic);
//不是get的方式
if (!m_IsGetData)
#if DEBUG_LOG_PROTO && DEBUG_MODEL
GameEntry.Log(LogCategory.Proto, "<color=#ffa200>发送消息:</color><color=#FFFB80>" + m_Url + "</color>");
GameEntry.Log(LogCategory.Proto, "<color=#ffdeb3>==>>" + json + "</color>");
#endif
GameEntry.Pool.EnqueueClassObject(m_Dic);
PostUrl(m_Url,json);
#endregion
#region GetUrl Get请求
//Get请求
private void GetUrl(string url)
UnityWebRequest request = UnityWebRequest.Get(url);
YouYou.GameEntry.Instance.StartCoroutine(Request(request));
#endregion
#region PostUrl Post请求
//Post请求
private void PostUrl(string url, string json)
//定义一个表单
WWWForm form = new WWWForm();
//给表单添加值
form.AddField("json",json);
//把url 和表单传入进去
UnityWebRequest request = UnityWebRequest.Post(url,form);
GameEntry.Instance.StartCoroutine(Request(request));
#endregion
#region Request 请求服务器
/*
* 功能:请求Web服务器
* request:UnityWebRequest请求的实体
*/
private IEnumerator Request(UnityWebRequest request)
//阻塞方法 和目标服务器建立连接,返回结果后才继续下一步
yield return request.SendWebRequest();
//如果有错误,重试与目标服务器连接(通信)
if (request.isNetworkError || request.isHttpError)
//报错了进行重试
if (m_CurrRetry > 0)
//过一段时间后再重新判断
yield return new WaitForSeconds(GameEntry.Http.RetryInterval);
//重试次数+1
++m_CurrRetry;
//如果<=配置的重试次数
if (m_CurrRetry <= GameEntry.Http.Retry)
#if DEBUG_LOG_PROTO && DEBUG_MODEL
//通过宏开关,决定要不要打印log
GameEntry.Log(LogCategory.Proto, "<color=#00eaff>请求URL:</color> <color=#00ff9c>0失败 当前重试次数1</color>", m_Url, m_CurrRetry);
#endif
//调用SendData,重新发送数据
SendData();
//结束本次携程
yield break;
//超过次数了,状态设置成有错误
IsBusy = false;
if (null != m_CallBack)
m_CallBackArgs.HasError = true;
m_CallBackArgs.Value = request.error;
//不是GetData 方式的话 打印一个log
if (!m_IsGetData)
#if DEBUG_LOG_PROTO && DEBUG_MODEL
GameEntry.Log(LogCategory.Proto, "<color=#00eaff>接收消息:</color> <color=#00ff9c>" + request.url + "</color>");
GameEntry.Log(LogCategory.Proto, "<color=#c5e1dc>==>>" + JsonUtility.ToJson(m_CallBackArgs) + "</color>");
#endif
m_CallBack(m_CallBackArgs);
//与主机建立连接
else
IsBusy = false;
if(null!=m_CallBack)
m_CallBackArgs.HasError = false;
m_CallBackArgs.Value = request.downloadHandler.text;
if (!m_IsGetData)
#if DEBUG_LOG_PROTO && DEBUG_MODEL
GameEntry.Log(LogCategory.Proto, "<color=#00eaff>接收消息:</color> <color=#00ff9c>" + request.url + "</color>");
GameEntry.Log(LogCategory.Proto, "<color=#c5e1dc>==>>" + JsonUtility.ToJson(m_CallBackArgs) + "</color>");
#endif
m_CallBackArgs.Data = request.downloadHandler.data;
m_CallBack(m_CallBackArgs);
//重试完毕,或者下载完毕
m_CurrRetry = 0;
m_Url = null;
if (null != m_Dic)
m_Dic.Clear();
m_Dic = null;
m_CallBackArgs.Data = null;
request.Dispose();
request = null;
//把Http访问器回池
GameEntry.Pool.EnqueueClassObject(this);
#endregion
HttpManager:Http服务器的管理类,记录了账号服务器的Url,通过HttpManager开启HttpRoutine。
HttpManager.cs 代码实现
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Myh
public class HttpManager : ManagerBase, IDisposable
//正式服 账号服务器url
private string m_WebAccountUrl;
//测试服 账号服务器url
private string m_TestWebAccountUrl;
//是否是测试环境
private bool m_IsTest;
//真实账号服务器Url
public string RealWebAccountUrl
get
return m_IsTest ? m_TestWebAccountUrl : m_WebAccountUrl;
//连接失败后重试次数
public int Retry
get;
private set;
//连接失败后重试间隔(单位:秒)
public float RetryInterval
get;
private set;
public override void Init()
//TODO:这些应该都要从设置里读取,可是现在没有,到时候回来改
m_WebAccountUrl = "";
m_TestWebAccountUrl = "";
m_IsTest = true;
Retry = 5;
RetryInterval = 2f;
public void SendData(string url, HttpSendDataCallBack cb, bool isPost = false,
bool isGetData = false, Dictionary<string, object> dic = null)
//从类对象池里,获取http访问器
HttpRoutine httpRoutine = YouYou.GameEntry.Pool.DequeueClassObject<HttpRoutine>();
httpRoutine.SendData(url, cb, isPost, isGetData, dic);
public void Dispose()
3 代码测试
Get访问网页会把网页内的html代码读出来;Getzip会把zip下载下来。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Myh;
using YouYou;
using UnityEngine;
public class TestHttp : ITest
private void TestGetWebUrl()
GameEntry.Http.SendData("https://www.baidu.com", (HttpCallBackArgs args) =>
GameEntry.Log(LogCategory.Normal, "httpCallbackArgs hasError:0 Value:1 data str:2",
args.HasError, args.Value, Encoding.UTF8.GetString(args.Data));
);
private void TestGetDownloadUrl()
//从web站点上下载eee.zip文件
GameEntry.Http.SendData("https://www.xxx.com/s/eee.zip", (HttpCallBackArgs args) =>
GameEntry.Log(LogCategory.Normal, "httpCallbackArgs hasError:0 Value:1 data str:2",
args.HasError, args.Value, Encoding.UTF8.GetString(args.Data));
);
public void OnTestStart()
public void OnTestUpdate()
if (Input.GetKeyDown(KeyCode.Q))
TestGetWebUrl();
else if (Input.GetKeyDown(KeyCode.E))
TestGetDownloadUrl();
4 引用
Get和Post对比:HTTP请求中Get和Post的区别是什么?_天才小熊猫oo的博客-CSDN博客
以上是关于U3D客户端框架之实现基于UnityWebRequest的Http服务 实现HttpCallBackArgs参数类HttpRoutine访问器HttpManager管理器的主要内容,如果未能解决你的问题,请参考以下文章
android-----XUtils框架之HttpUtils源码分析