/**
* 功能:利用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();
}
}