NetHelper.cs 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /**
  2. * 功能:利用WWW类实现网络(Http)通信.
  3. * 版本: V1.3 -> MonoSingleton
  4. * 历史:
  5. * v1.3 调整了基类,将nethelper纳入MonoSingleton之下管理. 2017.05.10 gwang
  6. * v1.2 修改了数据编码协议:
  7. * POST, 数据先json_encode然后deflate压缩, 返回值先inflate解压再json_decode.
  8. * GET , 数据先json_encode然后base64_encode再附加到url之后, 返回值先base64_decode解码再json_decode.
  9. * 2016.4.26 gwang
  10. * v1.1.1 修改返回值/请求值的类型, 从JObject->ResponseVo和RequestVo. 2016.4.14 gwang
  11. * v1.0.1 引自明星志愿项目, 并稍作调整, 主要是配套了下ErrCode. 2016.4.11 gwang
  12. */
  13. using UnityEngine;
  14. using UnityEngine.Networking;
  15. using System.Collections;
  16. using System.Collections.Generic;
  17. using System.Collections.Concurrent;
  18. using System.Threading;
  19. using System.Threading.Tasks;
  20. using System;
  21. using Newtonsoft.Json;
  22. using System.Text;
  23. /// <summary>
  24. /// HTTP 网络通讯辅助类
  25. /// </summary>
  26. [Obsolete("2022.9.7 已用HTTPHelper(并发通讯)替换. 此版本为串行通讯.")]
  27. public class NetHelper : MonoSingleton<NetHelper> // MonoBehaviour
  28. {
  29. // 目标通讯地址
  30. private string mHost = string.Empty;
  31. // 发送队列
  32. private ConcurrentQueue<NetPacket> mPacketQueue = new ConcurrentQueue<NetPacket>();
  33. // 当前网络状态
  34. private ENetStatus mNetStatus = ENetStatus.ENS_IDLE;
  35. public NetHelper()
  36. { //string targetUrl targetUrl;//
  37. mHost = Config_URL.Server_URL;
  38. }
  39. /// <summary>
  40. /// 提供Http Post方法
  41. /// </summary>
  42. /// <param name="ctx">传输内容</param>
  43. /// <param name="callback">回调函数</param>
  44. public void Post(int op, ReqVo ctx, int timeout, Action<RespVo> callback)
  45. {
  46. NetPacket packet = NetPacketFactory.CreatePacket();
  47. packet.url = mHost;
  48. packet.request = ctx;
  49. packet.handler = callback;
  50. packet.tsTimeout = timeout;
  51. mPacketQueue.Enqueue(packet);
  52. }
  53. /// <summary>
  54. /// 提供HTTP GET方法, 返回JSON形式
  55. /// </summary>
  56. /// <param name="url">请求地址</param>
  57. /// <param name="callback">回调函数</param>
  58. public void Get(string url, Dictionary<string, string> ctx, Action<RespVo> callback, int timeout)
  59. {
  60. NetPacket packet = NetPacketFactory.CreatePacket();
  61. if (null != ctx && ctx.Count > 0)
  62. {
  63. StringBuilder buffer = new StringBuilder();
  64. int i = 0;
  65. url += "?";
  66. foreach (KeyValuePair<String, String> kv in ctx)
  67. {
  68. buffer.AppendFormat("{0}{1}={2}", i > 0 ? "&" : "", kv.Key, kv.Value);
  69. ++i;
  70. }
  71. string paras = buffer.ToString();
  72. url += CSharpUtil.Base64Util.Encode(paras);
  73. }
  74. packet.url = url;
  75. packet.handler = callback;
  76. packet.tsTimeout = timeout;
  77. mPacketQueue.Enqueue(packet);
  78. }
  79. private void Start()
  80. {
  81. DontDestroyOnLoad(this);
  82. }
  83. /// <summary>
  84. /// 帧周期更新
  85. /// </summary>
  86. private void Update()
  87. {
  88. if (mNetStatus == ENetStatus.ENS_BUSY)
  89. return;
  90. if (mPacketQueue.TryDequeue(out NetPacket packet))
  91. {
  92. mNetStatus = ENetStatus.ENS_BUSY;
  93. StartCoroutine(Request(packet));
  94. }
  95. }
  96. private void RaiseResult(NetPacket packet)
  97. {
  98. mNetStatus = ENetStatus.ENS_IDLE;
  99. if (packet.errid == 0)
  100. {
  101. packet.handler(packet.response);
  102. }
  103. else
  104. {
  105. UI_CueDialog.Instance().Open("连接不到游戏服务器, 请检查网络.", "网络故障", E_DialogType.OneButton, ExitGame);
  106. throw new UnityException("网络模块故障, 需要应用上层逻辑处理或重置网络.");
  107. }
  108. }
  109. /// <summary>
  110. /// 网络请求
  111. /// </summary>
  112. /// <returns></returns>
  113. private IEnumerator Request(NetPacket packet)
  114. {
  115. WWW www = null;
  116. packet.tsRequest = DateTime.Now;
  117. DateTime maxTs = packet.tsRequest.AddSeconds(packet.tsTimeout);
  118. if (packet.request == null) // 处理Get请求
  119. {
  120. www = new WWW(packet.url);
  121. }
  122. else // 处理Post请求
  123. {
  124. string ctx = JsonConvert.SerializeObject(packet.request); // 序列化
  125. if (GlobalConfig.GAME_COMM_DEBUG)
  126. {
  127. var msg = ctx.Length > 1024 ? $"{ctx[..150]}...{ctx[^30..]}" : ctx;
  128. LogHelper.Log($"[SEND:]{msg}");
  129. }
  130. // 编码
  131. byte[] data = CSharpUtil.CompressUtil.Deflate(GlobalConfig.Encoding.GetBytes(ctx));
  132. www = new WWW(packet.url, data);
  133. }
  134. if (null == www || www.error != null)
  135. {
  136. LogHelper.Log("www error:" + www.error);
  137. packet.errid = ErrCode.net_connectno;
  138. packet.error = www.error;
  139. this.RaiseResult(packet);
  140. yield break;
  141. }
  142. // 超时检测
  143. while (false == www.isDone)
  144. {
  145. TimeSpan span = DateTime.Now - maxTs;
  146. if (span.TotalMilliseconds < 0)
  147. {
  148. yield return null;
  149. }
  150. else
  151. {
  152. packet.errid = ErrCode.net_timeout;
  153. packet.error = "timeout";
  154. this.RaiseResult(packet);
  155. yield break;
  156. }
  157. }
  158. // 网络错误检测
  159. if (www.error != null || www.text == null)
  160. {
  161. packet.errid = ErrCode.net_other;
  162. packet.error = www.error;
  163. this.RaiseResult(packet);
  164. yield break;
  165. }
  166. packet.tsResp = DateTime.Now;
  167. // 解码
  168. string decode = CSharpUtil.CompressUtil.InFlate(www.bytes, GlobalConfig.Encoding);
  169. if (null == decode || decode == "null")
  170. {
  171. packet.errid = ErrCode.net_decode;
  172. packet.error = "decodeerror";
  173. this.RaiseResult(packet);
  174. yield break;
  175. }
  176. if (GlobalConfig.GAME_COMM_DEBUG)
  177. {
  178. string format = decode; // decode.Replace("\\r\\n", "");
  179. var msg = format.Length > 1024 ? format[..150] + $"...({format.Length/1024:.0kb})..." + format[^30..] : format; // 约简日志长度
  180. var sp = (packet.tsResp - packet.tsRequest).TotalMilliseconds; // 计算往返耗时
  181. LogHelper.Log($"[RECV:]({sp:.00}ms){msg}");
  182. }
  183. packet.response = JsonConvert.DeserializeObject<RespVo>(decode); // 反序列化
  184. this.RaiseResult(packet);
  185. }
  186. /// <summary>
  187. /// 退出游戏
  188. /// </summary>
  189. private void ExitGame()
  190. {
  191. Application.Quit();
  192. }
  193. }