SocketConn.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. using System;
  2. using System.Net;
  3. using System.Net.Sockets;
  4. using System.Collections.Generic;
  5. using UnityEngine;
  6. public enum enSocketState
  7. {
  8. Connecting, //建立连接中
  9. Reconnecting, //重新连接中
  10. Connected, //连接成功
  11. Disconnecting, //断开连接中
  12. Disconnected, //连接断开
  13. ConnectedTimeout, //连接超时
  14. ConnectedError, //连接出错
  15. }
  16. public class SocketConn
  17. {
  18. string mName;
  19. string mLastIP;
  20. int mLastPort;
  21. Socket mSocket;
  22. enSocketState mPreSocketState;
  23. enSocketState mSocketState;
  24. ISocketHandler iHandler;
  25. float m_fConnectTimeout = 5f;
  26. float m_fBeginConnectTime = -1;
  27. bool m_bConnectExcept = false;
  28. string m_sConnectHost;
  29. int m_iConnectPort;
  30. int mConnectedFrameCount = 0;
  31. public enSocketState State { get { return mSocketState; } }
  32. public Socket Sock { get { return mSocket; } }
  33. public SocketConn(string name = "")
  34. {
  35. mName = name;
  36. mPreSocketState = enSocketState.Disconnected;
  37. mSocketState = enSocketState.Disconnected;
  38. mConnectedFrameCount = 0;
  39. m_bConnectExcept = false;
  40. }
  41. public void RegHandler(ISocketHandler handler)
  42. {
  43. iHandler = handler;
  44. }
  45. public void Resume()
  46. {
  47. mSocketState = enSocketState.ConnectedError;
  48. iHandler.OnError();
  49. }
  50. public void CustomUpdate()
  51. {
  52. if (m_fBeginConnectTime > 0 && Time.realtimeSinceStartup - m_fBeginConnectTime > m_fConnectTimeout)
  53. {
  54. Timeout();
  55. return;
  56. }
  57. if (m_bConnectExcept)
  58. {
  59. Disconnect();
  60. }
  61. if (mSocketState != enSocketState.Connected)
  62. {
  63. return;
  64. }
  65. if (mConnectedFrameCount == 1)
  66. {
  67. mConnectedFrameCount++;
  68. if (iHandler != null)
  69. {
  70. if (mPreSocketState == enSocketState.Reconnecting)
  71. iHandler.OnReconnect();
  72. else
  73. iHandler.OnConnect();
  74. }
  75. }
  76. try
  77. {
  78. //检测网络是否出错
  79. if (mSocket != null && mSocket.Poll(1, SelectMode.SelectError))
  80. {
  81. if (iHandler != null)
  82. {
  83. try {
  84. mSocketState = enSocketState.ConnectedError;
  85. iHandler.OnError();
  86. }
  87. catch (SocketException se)
  88. {
  89. iHandler.OnException(se);
  90. }
  91. }
  92. }
  93. }
  94. catch (System.Exception ex)
  95. {
  96. Debug.LogError("socket exception: " + ex.Message);
  97. }
  98. }
  99. public bool Connect(string host, int port, float timeout = 1f)
  100. {
  101. if (mSocketState != enSocketState.Disconnected)
  102. Disconnect();
  103. mPreSocketState = mSocketState;
  104. mSocketState = enSocketState.Connecting;
  105. m_fConnectTimeout = timeout;
  106. mConnectedFrameCount = 0;
  107. String newServerIp = "";
  108. AddressFamily newAddressFamily = AddressFamily.InterNetwork;
  109. if (!IPv6SupportMidleware.GetValidServerIpInfo(host, out newServerIp, out newAddressFamily))
  110. {
  111. Debug.LogError("IPv6SupportMidleware is Fail " + host);
  112. Disconnect();
  113. return false;
  114. }
  115. try
  116. {
  117. mSocket = new Socket(newAddressFamily, SocketType.Stream, ProtocolType.Tcp);
  118. IPAddress addr = IPAddress.Parse(newServerIp);
  119. IPEndPoint endpoint = new IPEndPoint(addr, port);
  120. Debug.LogWarning("Begin connect to Socket AddressFamily :" + newAddressFamily.ToString() + "ServerIp:" + newServerIp + ", Port:" + port);
  121. mSocket.NoDelay = true;
  122. mSocket.BeginConnect(endpoint, new AsyncCallback(EndConnect), new KeyValuePair<string, int>(host, port));
  123. m_fBeginConnectTime = Time.realtimeSinceStartup;
  124. return true;
  125. }
  126. catch (SocketException e)
  127. {
  128. Debug.LogError(e.Message);
  129. Disconnect();
  130. }
  131. return false;
  132. }
  133. public bool Reconnect()
  134. {
  135. if (string.IsNullOrEmpty(mLastIP))
  136. throw new Exception("cannot reconnect, last EndPoint is null");
  137. if (mSocketState != enSocketState.Disconnected)
  138. {
  139. Disconnect();
  140. return false;
  141. }
  142. mPreSocketState = mSocketState;
  143. mSocketState = enSocketState.Reconnecting;
  144. mConnectedFrameCount = 0;
  145. String newServerIp = "";
  146. AddressFamily newAddressFamily = AddressFamily.InterNetwork;
  147. if (!IPv6SupportMidleware.GetValidServerIpInfo(mLastIP, out newServerIp, out newAddressFamily))
  148. {
  149. Debug.LogError("IPv6SupportMidleware is Fail " + mLastIP);
  150. Disconnect();
  151. return false;
  152. }
  153. try
  154. {
  155. mSocket = new Socket(newAddressFamily, SocketType.Stream, ProtocolType.Tcp);
  156. mSocket.NoDelay = true;
  157. Debug.LogWarning("Begin connect to Socket AddressFamily :" + newAddressFamily.ToString() + "ServerIp:" + newServerIp + ", Port:" + mLastPort);
  158. mSocket.BeginConnect(newServerIp, mLastPort, new AsyncCallback(EndConnect), new KeyValuePair<string, int>(newServerIp, mLastPort));
  159. m_fBeginConnectTime = Time.realtimeSinceStartup;
  160. return true;
  161. }
  162. catch (SocketException e)
  163. {
  164. Debug.LogError(e.Message);
  165. Disconnect();
  166. }
  167. return false;
  168. }
  169. void EndConnect(IAsyncResult async)
  170. {
  171. Debug.Log("Connect AsyncCallback!");
  172. try
  173. {
  174. mSocket.EndConnect(async);
  175. if (mSocketState != enSocketState.Reconnecting)
  176. {
  177. KeyValuePair<string, int> pair = (KeyValuePair<string, int>)async.AsyncState;
  178. mLastIP = pair.Key;
  179. mLastPort = pair.Value;
  180. }
  181. mConnectedFrameCount = 1;
  182. mPreSocketState = mSocketState;
  183. mSocketState = enSocketState.Connected;
  184. }
  185. catch (SocketException e)
  186. {
  187. if (!e.NativeErrorCode.Equals(10035))
  188. {
  189. Debug.LogError(e.Message);
  190. // 当前是异步线程,等待主线程参数判定回调
  191. m_bConnectExcept = true;
  192. }
  193. }
  194. m_fBeginConnectTime = -1f;
  195. }
  196. public void Disconnect(bool ignoreEvent = false)
  197. {
  198. Debug.Log("Disconnect");
  199. if (mSocket != null)
  200. {
  201. mPreSocketState = mSocketState;
  202. mSocketState = enSocketState.Disconnecting;
  203. try { mSocket.Shutdown(SocketShutdown.Both); }
  204. catch (SocketException) { }
  205. finally
  206. {
  207. mSocket.Close(0);
  208. mSocket = null;
  209. }
  210. }
  211. if (!ignoreEvent)
  212. {
  213. if (iHandler != null)
  214. {
  215. iHandler.OnDisconnect();
  216. }
  217. }
  218. mPreSocketState = mSocketState;
  219. mSocketState = enSocketState.Disconnected;
  220. m_fBeginConnectTime = -1f;
  221. mConnectedFrameCount = 0;
  222. m_bConnectExcept = false;
  223. }
  224. private void Timeout()
  225. {
  226. if (iHandler != null)
  227. {
  228. iHandler.OnTimeout();
  229. }
  230. mPreSocketState = mSocketState;
  231. mSocketState = enSocketState.ConnectedTimeout;
  232. m_fBeginConnectTime = -1f;
  233. }
  234. }