/** * 功能:利用WWW类实现网络(Http)通信. * 版本: V1.3 -> MonoSingleton * 历史: * v1.3 调整了基类,将nethelper纳入MonoSingleton之下管理. 2017.05.10 gwang * v1.2 修改了数据编码协议: * POST, 数据先json_encode然后deflate压缩, 返回值先inflate解压再json_decode. * GET , 数据先json_encode然后base64_encode再附加到url之后, 返回值先base64_decode解码再json_decode. * 2016.4.26 gwang * v1.1.1 修改返回值/请求值的类型, 从JObject->ResponseVo和RequestVo. 2016.4.14 gwang * v1.0.1 引自明星志愿项目, 并稍作调整, 主要是配套了下ErrCode. 2016.4.11 gwang */ using UnityEngine; using UnityEngine.Networking; using System.Collections; using System.Collections.Generic; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; using System; using Newtonsoft.Json; using System.Text; /// /// HTTP 网络通讯辅助类 /// [Obsolete("2022.9.7 已用HTTPHelper(并发通讯)替换. 此版本为串行通讯.")] public class NetHelper : MonoSingleton // MonoBehaviour { // 目标通讯地址 private string mHost = string.Empty; // 发送队列 private ConcurrentQueue mPacketQueue = new ConcurrentQueue(); // 当前网络状态 private ENetStatus mNetStatus = ENetStatus.ENS_IDLE; public NetHelper() { //string targetUrl targetUrl;// mHost = Config_URL.Server_URL; } /// /// 提供Http Post方法 /// /// 传输内容 /// 回调函数 public void Post(int op, ReqVo ctx, int timeout, Action callback) { NetPacket packet = NetPacketFactory.CreatePacket(); packet.url = mHost; packet.request = ctx; packet.handler = callback; packet.tsTimeout = timeout; mPacketQueue.Enqueue(packet); } /// /// 提供HTTP GET方法, 返回JSON形式 /// /// 请求地址 /// 回调函数 public void Get(string url, Dictionary ctx, Action callback, int timeout) { NetPacket packet = NetPacketFactory.CreatePacket(); if (null != ctx && ctx.Count > 0) { StringBuilder buffer = new StringBuilder(); int i = 0; url += "?"; foreach (KeyValuePair kv in ctx) { buffer.AppendFormat("{0}{1}={2}", i > 0 ? "&" : "", kv.Key, kv.Value); ++i; } string paras = buffer.ToString(); url += CSharpUtil.Base64Util.Encode(paras); } packet.url = url; packet.handler = callback; packet.tsTimeout = timeout; mPacketQueue.Enqueue(packet); } private void Start() { DontDestroyOnLoad(this); } /// /// 帧周期更新 /// private void Update() { if (mNetStatus == ENetStatus.ENS_BUSY) return; if (mPacketQueue.TryDequeue(out NetPacket packet)) { mNetStatus = ENetStatus.ENS_BUSY; StartCoroutine(Request(packet)); } } private void RaiseResult(NetPacket packet) { mNetStatus = ENetStatus.ENS_IDLE; if (packet.errid == 0) { packet.handler(packet.response); } else { UI_CueDialog.Instance().Open("连接不到游戏服务器, 请检查网络.", "网络故障", E_DialogType.OneButton, ExitGame); throw new UnityException("网络模块故障, 需要应用上层逻辑处理或重置网络."); } } /// /// 网络请求 /// /// private IEnumerator Request(NetPacket packet) { WWW www = null; packet.tsRequest = DateTime.Now; DateTime maxTs = packet.tsRequest.AddSeconds(packet.tsTimeout); if (packet.request == null) // 处理Get请求 { www = new WWW(packet.url); } else // 处理Post请求 { string ctx = JsonConvert.SerializeObject(packet.request); // 序列化 if (GlobalConfig.GAME_COMM_DEBUG) { var msg = ctx.Length > 1024 ? $"{ctx[..150]}...{ctx[^30..]}" : ctx; LogHelper.Log($"[SEND:]{msg}"); } // 编码 byte[] data = CSharpUtil.CompressUtil.Deflate(GlobalConfig.Encoding.GetBytes(ctx)); www = new WWW(packet.url, data); } if (null == www || www.error != null) { LogHelper.Log("www error:" + www.error); packet.errid = ErrCode.net_connectno; packet.error = www.error; this.RaiseResult(packet); yield break; } // 超时检测 while (false == www.isDone) { TimeSpan span = DateTime.Now - maxTs; if (span.TotalMilliseconds < 0) { yield return null; } else { packet.errid = ErrCode.net_timeout; packet.error = "timeout"; this.RaiseResult(packet); yield break; } } // 网络错误检测 if (www.error != null || www.text == null) { packet.errid = ErrCode.net_other; packet.error = www.error; this.RaiseResult(packet); yield break; } packet.tsResp = DateTime.Now; // 解码 string decode = CSharpUtil.CompressUtil.InFlate(www.bytes, GlobalConfig.Encoding); if (null == decode || decode == "null") { packet.errid = ErrCode.net_decode; packet.error = "decodeerror"; this.RaiseResult(packet); yield break; } if (GlobalConfig.GAME_COMM_DEBUG) { string format = decode; // decode.Replace("\\r\\n", ""); var msg = format.Length > 1024 ? format[..150] + $"...({format.Length/1024:.0kb})..." + format[^30..] : format; // 约简日志长度 var sp = (packet.tsResp - packet.tsRequest).TotalMilliseconds; // 计算往返耗时 LogHelper.Log($"[RECV:]({sp:.00}ms){msg}"); } packet.response = JsonConvert.DeserializeObject(decode); // 反序列化 this.RaiseResult(packet); } /// /// 退出游戏 /// private void ExitGame() { Application.Quit(); } }