Server.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using CScript.Utilities;
  5. using System.Threading;
  6. using CScript.Entity;
  7. using System;
  8. using System.Text;
  9. using System.Net;
  10. using System.Net.Sockets;
  11. using System.IO;
  12. using CScript.App;
  13. namespace CScript.Net
  14. {
  15. public class Server : MonoSingleton<Server>
  16. {
  17. //const int DEF_RECV_BUFFER_SIZE = 4096000;
  18. const int DEF_RECV_BUFFER_SIZE = 409600 * 2;
  19. const int DEF_TRY_CONNECT_TIMES = 3;
  20. const int NetConnectTimeout = 10000;// connect wait milliseconds
  21. public const int NET_ERROR_UNKNOW_PROTOCOL = 2; //协议错误
  22. public const int NET_ERROR_SEND_EXCEPTION = 1000; //发送异常
  23. public const int NET_ERROR_ILLEGAL_PACKAGE = 1001; //接受到错误数据包
  24. public const int NET_ERROR_ZERO_BYTE = 1002; //收发0字节
  25. public const int NET_ERROR_PACKAGE_TIMEOUT = 1003; //收包超时
  26. public const int NET_ERROR_PROXY_TIMEOUT = 1004; //proxy超时
  27. public const int NET_ERROR_FAIL_TO_CONNECT = 1005; //3次连接不上
  28. public const int NET_ERROR_PROXY_ERROR = 1006; //proxy重启
  29. public const int NET_ERROR_ON_DESTROY = 1007; //结束的时候,关闭网络连接
  30. public const int NET_ERROR_ON_KICKOUT = 25; //被踢了
  31. private List<string> _frontTextAssetList;
  32. private List<string> _sideTextAssetList;
  33. private List<Texture2D> _texture2Ds;
  34. private Thread _parseThread;
  35. private Thread _drawThread;
  36. private Thread _recvThread;
  37. private int _dataCount = 10;
  38. private List<int> _tempDataValue = new List<int>();
  39. private string[] _tempFrontStr;
  40. private string[] _sideFrontStr;
  41. public List<byte[]> messageQueue;
  42. public delegate void ConnectEventHandler(int result, string reason);
  43. public delegate void ExpectPackageEventHandler();
  44. public event ConnectEventHandler OnConnect;
  45. public event ConnectEventHandler OnDisconnect;
  46. public event ExpectPackageEventHandler OnExpectPackageTimeout;
  47. public event ExpectPackageEventHandler OnExpectPackageResume;
  48. private IPEndPoint _address;
  49. private Socket _clientSocket;
  50. private MemoryStream _sendBuffer = new MemoryStream();
  51. private MemoryStream _receiveBuffer = new MemoryStream(DEF_RECV_BUFFER_SIZE);
  52. private Queue<string> _sendQueue = new Queue<string>();
  53. private bool _connecting = false;
  54. private int _retryTimes = 0;// 重试
  55. private float _lastSendTime = 0;
  56. private int _retryTimesTotal = DEF_TRY_CONNECT_TIMES;
  57. private int _sendOffset = 0;
  58. public bool running { get; set; }
  59. public PackageHandler packageHandler = new PackageHandler(null);
  60. public void Init(string serverIP, int port)
  61. {
  62. this._address = new IPEndPoint(IPAddress.Parse(serverIP), port);
  63. running = true;
  64. }
  65. public void Connect(int times = DEF_TRY_CONNECT_TIMES)
  66. {
  67. if (this._connecting)
  68. {
  69. return;
  70. }
  71. if (this._clientSocket != null)
  72. {
  73. this._clientSocket.Close();
  74. }
  75. if (this._address == default(IPEndPoint))
  76. {
  77. throw new Exception("Please Init first.");
  78. }
  79. Debug.Log("DoConnect");
  80. this._connecting = true;
  81. this._retryTimes = 0;
  82. this.DoConnect();
  83. }
  84. protected virtual void RaiseConnected(int result, string reason)
  85. {
  86. if (_recvThread == null || !_recvThread.IsAlive)
  87. {
  88. _recvThread = new Thread(Recv);
  89. _recvThread.Start();
  90. }
  91. ConnectEventHandler handler = OnConnect;
  92. if (handler != null)
  93. {
  94. handler(result, reason);
  95. }
  96. NetDistribute.Instance.OnConnect(result==0?true:false, reason);
  97. }
  98. public virtual void RaiseDisonnected(int result, string reason = "")
  99. {
  100. ConnectEventHandler handler = OnDisconnect;
  101. if (handler != null)
  102. {
  103. handler(result, reason);
  104. }
  105. NetDistribute.Instance.OnDisconnect(result, reason);
  106. }
  107. protected virtual void RaiseExpectPackageTimeout()
  108. {
  109. ExpectPackageEventHandler handler = OnExpectPackageTimeout;
  110. if (handler != null)
  111. {
  112. handler();
  113. }
  114. }
  115. protected virtual void RaiseExpectPackageResume()
  116. {
  117. ExpectPackageEventHandler handler = OnExpectPackageResume;
  118. if (handler != null)
  119. {
  120. handler();
  121. }
  122. }
  123. public bool Connected
  124. {
  125. get
  126. {
  127. return (_clientSocket != default(Socket)) ? _clientSocket.Connected : false;
  128. }
  129. }
  130. public void Reset()
  131. {
  132. this._connecting = false;
  133. this.OnConnect = null;
  134. this.OnDisconnect = null;
  135. this.OnExpectPackageTimeout = null;
  136. this.OnExpectPackageResume = null;
  137. }
  138. void DoConnect()
  139. {
  140. Debug.Log("NetClient.DoConnect on " + this._address.ToString());
  141. try
  142. {
  143. if (this._clientSocket != null)
  144. {
  145. this._clientSocket.Close();
  146. }
  147. this._clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  148. this._clientSocket.Blocking = true;
  149. Debug.Log(string.Format("Connect[{0}] to server {1}", this._retryTimes, this._address) + "\n");
  150. IAsyncResult result = this._clientSocket.BeginConnect(this._address, null, null);
  151. bool success = result.AsyncWaitHandle.WaitOne(NetConnectTimeout);
  152. if (success)
  153. {
  154. this._clientSocket.EndConnect(result);
  155. }
  156. }
  157. catch (SocketException ex)
  158. {
  159. if (ex.SocketErrorCode == SocketError.ConnectionRefused)
  160. {
  161. this.CloseConnection(NET_ERROR_FAIL_TO_CONNECT);
  162. }
  163. Debug.LogErrorFormat("DoConnect SocketException:[{0},{1},{2}]{3} ", ex.ErrorCode, ex.SocketErrorCode, ex.NativeErrorCode, ex.ToString());
  164. }
  165. catch (Exception e)
  166. {
  167. Debug.Log("DoConnect Exception:" + e.ToString() + "\n");
  168. }
  169. if (this._clientSocket.Connected)
  170. {
  171. this._clientSocket.Blocking = false;
  172. this.RaiseConnected(0, "Success");
  173. }
  174. else
  175. {
  176. this._retryTimes++;
  177. if (this._retryTimes >= this._retryTimesTotal)
  178. {
  179. this.RaiseConnected(1, "Cannot connect to server");
  180. }
  181. }
  182. this._connecting = false;
  183. }
  184. public void CloseConnection(int errCode)
  185. {
  186. Debug.LogWarning("CloseConnection(), errorCode: " + errCode.ToString());
  187. this._connecting = false;
  188. if (this._clientSocket != null)
  189. {
  190. this._clientSocket.Close();
  191. }
  192. //清空缓冲区
  193. this._receiveBuffer.Position = 0;
  194. this._receiveBuffer.SetLength(0);
  195. this.packageHandler.Reset();
  196. switch (errCode)
  197. {
  198. case NET_ERROR_UNKNOW_PROTOCOL:
  199. {
  200. //致命错误,停止网络服务
  201. this.running = false;
  202. }
  203. break;
  204. case NET_ERROR_FAIL_TO_CONNECT:
  205. case NET_ERROR_PROXY_TIMEOUT:
  206. case NET_ERROR_PROXY_ERROR:
  207. //NetworkManager.Instance.dropCurMessage();
  208. //NetworkManager.Instance.Connect();
  209. break;
  210. //离线处理
  211. case NET_ERROR_ON_KICKOUT:
  212. case NET_ERROR_ZERO_BYTE:
  213. case NET_ERROR_ILLEGAL_PACKAGE:
  214. case NET_ERROR_SEND_EXCEPTION:
  215. case NET_ERROR_PACKAGE_TIMEOUT:
  216. default:
  217. this._lastSendTime = 0;
  218. this.RaiseDisonnected(errCode);
  219. break;
  220. }
  221. }
  222. public void SendTCPMessage(string message)
  223. {
  224. if (!running)
  225. {
  226. return;
  227. }
  228. if (!this.Connected)
  229. {
  230. //this.receiveBuffer.Position = 0;
  231. //this.sendBuffer.Position = sendOffset = 0;
  232. this.Connect();
  233. Debug.Log("Connect Server before Send Message!");
  234. return;
  235. }
  236. _sendQueue.Enqueue(message);
  237. if (this._lastSendTime == 0)
  238. {
  239. this._lastSendTime = Time.time;
  240. }
  241. }
  242. bool KeepConnect()
  243. {
  244. if (this._connecting)
  245. {
  246. return false;
  247. }
  248. if (this._address == null)
  249. return false;
  250. if (this.Connected)
  251. {
  252. return true;
  253. }
  254. if (this._retryTimes < this._retryTimesTotal)
  255. {
  256. this.Connect();
  257. }
  258. return false;
  259. }
  260. bool ProcessRecv()
  261. {
  262. bool ret = false;
  263. try
  264. {
  265. if (this._clientSocket.Blocking)
  266. {
  267. Debug.Log("this.clientSocket.Blocking = true\n");
  268. }
  269. bool error = this._clientSocket.Poll(0, SelectMode.SelectError);
  270. if (error)
  271. {
  272. Debug.Log("ProcessRecv Poll SelectError\n");
  273. this.CloseConnection(NET_ERROR_SEND_EXCEPTION);
  274. return false;
  275. }
  276. ret = this._clientSocket.Poll(0, SelectMode.SelectRead);
  277. if (ret)
  278. {
  279. int n = this._clientSocket.Receive(this._receiveBuffer.GetBuffer(), 0, this._receiveBuffer.Capacity, SocketFlags.None);
  280. if (n <= 0)
  281. {
  282. this.CloseConnection(NET_ERROR_ZERO_BYTE);
  283. return false;
  284. }
  285. this.packageHandler.ReceiveData(this._receiveBuffer.GetBuffer(), 0, n);
  286. }
  287. }
  288. catch (Exception e)
  289. {
  290. Debug.Log("ProcessReceive exception:" + e.ToString() + "\n");
  291. this.CloseConnection(NET_ERROR_ILLEGAL_PACKAGE);
  292. return false;
  293. }
  294. return true;
  295. }
  296. bool ProcessSend()
  297. {
  298. bool ret = false;
  299. try
  300. {
  301. if (this._clientSocket.Blocking)
  302. {
  303. Debug.Log("this.clientSocket.Blocking = true\n");
  304. }
  305. bool error = this._clientSocket.Poll(0, SelectMode.SelectError);
  306. if (error)
  307. {
  308. Debug.Log("ProcessSend Poll SelectError\n");
  309. this.CloseConnection(NET_ERROR_SEND_EXCEPTION);
  310. return false;
  311. }
  312. ret = this._clientSocket.Poll(0, SelectMode.SelectWrite);
  313. if (ret)
  314. {
  315. //sendStream exist data
  316. if (this._sendBuffer.Position > this._sendOffset)
  317. {
  318. int bufsize = (int)(this._sendBuffer.Position - this._sendOffset);
  319. int n = this._clientSocket.Send(this._sendBuffer.GetBuffer(), this._sendOffset, bufsize, SocketFlags.None);
  320. if (n <= 0)
  321. {
  322. this.CloseConnection(NET_ERROR_ZERO_BYTE);
  323. return false;
  324. }
  325. this._sendOffset += n;
  326. if (this._sendOffset >= this._sendBuffer.Position)
  327. {
  328. this._sendOffset = 0;
  329. this._sendBuffer.Position = 0;
  330. this._sendQueue.Dequeue();//remove message when send complete
  331. }
  332. }
  333. else
  334. {
  335. //fetch package from sendQueue
  336. if (this._sendQueue.Count > 0)
  337. {
  338. string message = this._sendQueue.Peek();
  339. byte[] package = Encoding.UTF8.GetBytes(message);
  340. this._sendBuffer.Write(package, 0, package.Length);
  341. }
  342. }
  343. }
  344. }
  345. catch (Exception e)
  346. {
  347. Debug.Log("ProcessSend exception:" + e.ToString() + "\n");
  348. this.CloseConnection(NET_ERROR_SEND_EXCEPTION);
  349. return false;
  350. }
  351. return true;
  352. }
  353. void ProceeMessage()
  354. {
  355. //MessageDistributer.Instance.Distribute();
  356. }
  357. void Recv()
  358. {
  359. while (running)
  360. {
  361. if (this.KeepConnect())
  362. {
  363. ProcessSend();
  364. Debug.Log("开始: " + DateTime.Now.Hour + " :" + DateTime.Now.Minute + " : " + DateTime.Now.Second);
  365. if (this.ProcessRecv())
  366. {
  367. }
  368. Debug.Log("结束: " + DateTime.Now.Hour + " :" + DateTime.Now.Minute + " : " + DateTime.Now.Second);
  369. }
  370. Thread.Sleep(30);
  371. }
  372. }
  373. private void OnDestroy()
  374. {
  375. Close();
  376. }
  377. public void Close()
  378. {
  379. if(_recvThread!=null && _recvThread.IsAlive)
  380. _recvThread.Abort();
  381. this.running = false;
  382. }
  383. }
  384. }