NetWorkBehaviour.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /****************************************************************************
  2. * Copyright 2019 Nreal Techonology Limited. All rights reserved.
  3. *
  4. * This file is part of NRSDK.
  5. *
  6. * https://www.nreal.ai/
  7. *
  8. *****************************************************************************/
  9. namespace NRKernal.Experimental.NetWork
  10. {
  11. using System;
  12. using System.Collections;
  13. using UnityEngine;
  14. using NRKernal;
  15. using System.Collections.Generic;
  16. using LitJson;
  17. using System.Text;
  18. /// <summary> An observer view net worker. </summary>
  19. public class NetWorkBehaviour
  20. {
  21. /// <summary> The net work client. </summary>
  22. protected NetWorkClient m_NetWorkClient;
  23. /// <summary> The limit waitting time. </summary>
  24. private const float limitWaittingTime = 5f;
  25. /// <summary> True if is connected, false if not. </summary>
  26. private bool m_IsConnected = false;
  27. /// <summary> True if is jonin success, false if not. </summary>
  28. private bool m_IsJoninSuccess = false;
  29. /// <summary> True if is closed, false if not. </summary>
  30. private bool m_IsClosed = false;
  31. private Coroutine checkServerAvailableCoroutine = null;
  32. private Dictionary<ulong, Action<JsonData>> _ResponseEvents = new Dictionary<ulong, Action<JsonData>>();
  33. public virtual void Listen()
  34. {
  35. if (m_NetWorkClient == null)
  36. {
  37. m_NetWorkClient = new NetWorkClient();
  38. m_NetWorkClient.OnDisconnect += OnDisconnect;
  39. m_NetWorkClient.OnConnect += OnConnected;
  40. m_NetWorkClient.OnJoinRoomResult += OnJoinRoomResult;
  41. m_NetWorkClient.OnMessageResponse += OnMessageResponse;
  42. }
  43. }
  44. private void OnMessageResponse(byte[] data)
  45. {
  46. ulong msgid = BitConverter.ToUInt64(data, 0);
  47. Action<JsonData> callback;
  48. if (!_ResponseEvents.TryGetValue(msgid, out callback))
  49. {
  50. NRDebugger.Warning("[NetWorkBehaviour] can not find the msgid bind event:" + msgid);
  51. return;
  52. }
  53. // Remove the header to get the msg.
  54. byte[] result = new byte[data.Length - sizeof(ulong)];
  55. Array.Copy(data, sizeof(ulong), result, 0, result.Length);
  56. string json = Encoding.UTF8.GetString(result);
  57. callback?.Invoke(JsonMapper.ToObject(json));
  58. NRDebugger.Info("[NetWorkBehaviour] OnMessageResponse hit...");
  59. _ResponseEvents.Remove(msgid);
  60. }
  61. /// <summary> Check server available. </summary>
  62. /// <param name="ip"> The IP.</param>
  63. /// <param name="callback"> The callback.</param>
  64. public void CheckServerAvailable(string ip, Action<bool> callback)
  65. {
  66. if (string.IsNullOrEmpty(ip))
  67. {
  68. callback?.Invoke(false);
  69. }
  70. else
  71. {
  72. if (checkServerAvailableCoroutine != null)
  73. {
  74. NRKernalUpdater.Instance.StopCoroutine(checkServerAvailableCoroutine);
  75. }
  76. checkServerAvailableCoroutine = NRKernalUpdater.Instance.StartCoroutine(CheckServerAvailableCoroutine(ip, callback));
  77. }
  78. }
  79. /// <summary> Check server available coroutine. </summary>
  80. /// <param name="ip"> The IP.</param>
  81. /// <param name="callback"> The callback.</param>
  82. /// <returns> An IEnumerator. </returns>
  83. private IEnumerator CheckServerAvailableCoroutine(string ip, Action<bool> callback)
  84. {
  85. // Start to connect the server.
  86. m_NetWorkClient.Connect(ip, 6000);
  87. float timeLast = 0;
  88. while (!m_IsConnected)
  89. {
  90. if (timeLast > limitWaittingTime || m_IsClosed)
  91. {
  92. NRDebugger.Info("[ObserverView] Connect the server TimeOut!");
  93. callback?.Invoke(false);
  94. yield break;
  95. }
  96. timeLast += Time.deltaTime;
  97. yield return new WaitForEndOfFrame();
  98. }
  99. // Start to enter the room.
  100. m_NetWorkClient.EnterRoomRequest();
  101. timeLast = 0;
  102. while (!m_IsJoninSuccess)
  103. {
  104. if (timeLast > limitWaittingTime || m_IsClosed)
  105. {
  106. NRDebugger.Info("[ObserverView] Join the server TimeOut!");
  107. callback?.Invoke(false);
  108. yield break;
  109. }
  110. timeLast += Time.deltaTime;
  111. yield return new WaitForEndOfFrame();
  112. }
  113. callback?.Invoke(true);
  114. }
  115. public void SendMsg(JsonData data, Action<JsonData> onResponse, float timeout = 3)
  116. {
  117. NRKernalUpdater.Instance.StartCoroutine(SendMessage(data, onResponse, timeout));
  118. }
  119. private IEnumerator SendMessage(JsonData data, Action<JsonData> onResponse, float timeout)
  120. {
  121. if (data == null)
  122. {
  123. NRDebugger.Error("[NetWorkBehaviour] data is null!");
  124. yield break;
  125. }
  126. // Add msgid(current timestamp) as the header.
  127. ulong msgid = NRTools.GetTimeStamp();
  128. byte[] json_data = Encoding.UTF8.GetBytes(data.ToJson());
  129. byte[] total_data = new byte[json_data.Length + sizeof(ulong)];
  130. Array.Copy(BitConverter.GetBytes(msgid), 0, total_data, 0, sizeof(ulong));
  131. Array.Copy(json_data, 0, total_data, sizeof(ulong), json_data.Length);
  132. if (onResponse != null)
  133. {
  134. Action<JsonData> onResult;
  135. AsyncTask<JsonData> asyncTask = new AsyncTask<JsonData>(out onResult);
  136. _ResponseEvents[msgid] = onResult;
  137. m_NetWorkClient.SendMessage(total_data);
  138. NRKernalUpdater.Instance.StartCoroutine(SendMsgTimeOut(msgid, timeout));
  139. yield return asyncTask.WaitForCompletion();
  140. onResponse?.Invoke(asyncTask.Result);
  141. }
  142. else
  143. {
  144. m_NetWorkClient.SendMessage(total_data);
  145. }
  146. }
  147. private IEnumerator SendMsgTimeOut(UInt64 id, float timeout)
  148. {
  149. yield return new WaitForSeconds(timeout);
  150. Action<JsonData> callback;
  151. if (_ResponseEvents.TryGetValue(id, out callback))
  152. {
  153. NRDebugger.Warning("[NetWorkBehaviour] Send msg timeout, id:{0}", id);
  154. JsonData json = new JsonData();
  155. json["success"] = false;
  156. callback?.Invoke(json);
  157. }
  158. }
  159. #region Net msg
  160. /// <summary> Executes the 'connected' action. </summary>
  161. private void OnConnected()
  162. {
  163. NRDebugger.Info("[NetWorkBehaviour] OnConnected...");
  164. m_IsConnected = true;
  165. }
  166. /// <summary> Executes the 'disconnect' action. </summary>
  167. private void OnDisconnect()
  168. {
  169. NRDebugger.Info("[NetWorkBehaviour] OnDisconnect...");
  170. this.Close();
  171. }
  172. /// <summary> Executes the 'join room result' action. </summary>
  173. /// <param name="result"> True to result.</param>
  174. private void OnJoinRoomResult(bool result)
  175. {
  176. NRDebugger.Info("[NetWorkBehaviour] OnJoinRoomResult :" + result);
  177. m_IsJoninSuccess = result;
  178. if (!result)
  179. {
  180. this.Close();
  181. }
  182. }
  183. #endregion
  184. /// <summary> Closes this object. </summary>
  185. public virtual void Close()
  186. {
  187. if (checkServerAvailableCoroutine != null)
  188. {
  189. NRKernalUpdater.Instance.StopCoroutine(checkServerAvailableCoroutine);
  190. }
  191. m_NetWorkClient.ExitRoomRequest();
  192. m_NetWorkClient?.Dispose();
  193. m_NetWorkClient = null;
  194. checkServerAvailableCoroutine = null;
  195. m_IsClosed = true;
  196. }
  197. }
  198. }