TCPClient.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. using System;
  2. using System.IO;
  3. using System.IO.Compression;
  4. using System.Net;
  5. using System.Net.Sockets;
  6. using System.Threading;
  7. using Fort23.Core;
  8. using Fort23.UTool;
  9. using Task = System.Threading.Tasks.Task;
  10. namespace Core.KCPTool
  11. {
  12. public class TCPClient : IClientConnection
  13. {
  14. private byte[] buffData = new byte[6553];
  15. private Socket socket;
  16. public bool IsConnection { get; set; }
  17. public bool disconnect { get; set; }
  18. //记录半包数据
  19. private bool isBufferData;
  20. private byte[] lastBuffData;
  21. private int lastCount;
  22. private byte lastSendType;
  23. //数据结束
  24. //尾包
  25. private byte[] weiBaoBuffData;
  26. private Thread _udpClientThread;
  27. private IClient client;
  28. private long playerId;
  29. private bool isFinish;
  30. public bool isAwaitReConnect { get; set; }
  31. private bool isStartConnect;
  32. private CTask _cTask;
  33. public bool serveError;
  34. public TCPClient()
  35. {
  36. }
  37. public async Task Connect(IPEndPoint endPoint, long playerId, IClient client)
  38. {
  39. if (isStartConnect)
  40. {
  41. return;
  42. }
  43. serveError = false;
  44. _cTask = CTask.Create(false);
  45. isStartConnect = true;
  46. this.client = client;
  47. this.playerId = playerId;
  48. try
  49. {
  50. socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  51. await socket.ConnectAsync(endPoint);
  52. isStartConnect = false;
  53. }
  54. catch (Exception e)
  55. {
  56. disconnect = true;
  57. LogTool.Exception(e);
  58. isStartConnect = false;
  59. serveError = true;
  60. return;
  61. }
  62. IsConnection = false;
  63. disconnect = false;
  64. _udpClientThread = new Thread(TheUpdate);
  65. _udpClientThread.Start();
  66. byte[] data = SocketTool.LongToByte(playerId);
  67. SendToServer(SendDataType.ShakeHands, data);
  68. await _cTask;
  69. }
  70. /// <summary>
  71. /// 重新链接
  72. /// </summary>
  73. public async void ReConnect(IPEndPoint endPoint, int gameFrame)
  74. {
  75. // if (isStartConnect)
  76. // {
  77. // return;
  78. // }
  79. //
  80. // if (socket != null)
  81. // {
  82. // socket.Dispose();
  83. // socket = null;
  84. // }
  85. //
  86. // isStartConnect = true;
  87. // Thread.Sleep(10);
  88. // LogTool.Error("开始重新链接" + gameFrame);
  89. //
  90. // try
  91. // {
  92. // socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
  93. // await socket.ConnectAsync(endPoint);
  94. // isStartConnect = false;
  95. // }
  96. // catch (Exception e)
  97. // {
  98. // disconnect = true;
  99. // LogTool.Exception(e);
  100. // isStartConnect = false;
  101. // return;
  102. // }
  103. //
  104. // disconnect = false;
  105. // _udpClientThread = new Thread(TheUpdate);
  106. // _udpClientThread.Start();
  107. // isAwaitReConnect = true;
  108. byte[] data = SocketTool.LongToByte(playerId);
  109. byte[] gameFrameByte = SocketTool.IntToByte(gameFrame);
  110. byte[] buffer = new byte[data.Length + gameFrameByte.Length];
  111. Array.Copy(data, 0, buffer, 0, data.Length);
  112. Array.Copy(gameFrameByte, 0, buffer, data.Length, gameFrameByte.Length);
  113. SendToServer(SendDataType.GetGameFrameByte, buffer);
  114. }
  115. private void TheUpdate()
  116. {
  117. while (socket != null)
  118. {
  119. try
  120. {
  121. int count = socket.Receive(buffData);
  122. if (count <= 0)
  123. {
  124. Thread.Sleep(1);
  125. return;
  126. }
  127. // LogTool.Log("数据来了" + count);
  128. try
  129. {
  130. int currCount = 0;
  131. int startIndex = 0;
  132. // bool isEnd = false;
  133. while (currCount < count)
  134. {
  135. // isEnd = true;
  136. byte[] data = null;
  137. byte sendType = 0;
  138. int cdShort = 0;
  139. if (!isBufferData)
  140. {
  141. if (weiBaoBuffData != null)
  142. {
  143. int maxCount = 6553500;
  144. if (count + weiBaoBuffData.Length > maxCount)
  145. {
  146. maxCount = count + weiBaoBuffData.Length;
  147. }
  148. // LogTool.Log("修复包太短__" + count + "___" + weiBaoBuffData.Length);
  149. byte[] newBuff = new byte[maxCount];
  150. Array.Copy(weiBaoBuffData, 0, newBuff, 0, weiBaoBuffData.Length);
  151. Array.Copy(buffData, 0, newBuff, weiBaoBuffData.Length, count);
  152. buffData = newBuff;
  153. count += weiBaoBuffData.Length;
  154. // LogTool.Log("修复包后太短__" + count);
  155. if (count < 6)
  156. {
  157. weiBaoBuffData = new byte[count];
  158. // LogTool.Log("包太短222__" + count);
  159. Array.Copy(buffData, currCount, weiBaoBuffData, 0, count);
  160. break;
  161. }
  162. else
  163. {
  164. weiBaoBuffData = null;
  165. }
  166. }
  167. else
  168. {
  169. if (count - currCount < 5)
  170. {
  171. weiBaoBuffData = new byte[count];
  172. // LogTool.Log("包太短__" + count);
  173. Array.Copy(buffData, currCount, weiBaoBuffData, 0, count);
  174. break;
  175. }
  176. }
  177. }
  178. if (!isBufferData)
  179. {
  180. sendType = buffData[currCount];
  181. currCount++;
  182. byte[] dataBuffLanl = new byte[4];
  183. dataBuffLanl[0] = buffData[currCount];
  184. currCount++;
  185. dataBuffLanl[1] = buffData[currCount];
  186. currCount++;
  187. dataBuffLanl[2] = buffData[currCount];
  188. currCount++;
  189. dataBuffLanl[3] = buffData[currCount];
  190. currCount++;
  191. cdShort = (SocketTool.ByteToInt(dataBuffLanl));
  192. // LogTool.Log("数据到来" + cdShort + "__" + count + "_" + sendType);
  193. if ((currCount + cdShort) > count) //处理半包情况
  194. {
  195. lastBuffData = new byte[count - currCount];
  196. lastCount = cdShort;
  197. lastSendType = sendType;
  198. Array.Copy(buffData, currCount, lastBuffData, 0, lastBuffData.Length);
  199. // LogTool.Log("数据只有一半" + count + "__" + currCount + "___" + cdShort);
  200. isBufferData = true;
  201. break;
  202. }
  203. else
  204. {
  205. // LogTool.Log(currCount + "_收到长度:" + cdShort + "_Max" + count);
  206. data = new byte[cdShort];
  207. Array.Copy(buffData, currCount, data, 0, data.Length);
  208. }
  209. }
  210. else if (lastCount - lastBuffData.Length > count)
  211. {
  212. // LogTool.Log("数据只有一半的一半" + count + "__" + lastCount + "___" + lastBuffData.Length);
  213. byte[] newLastBuffData = new byte[lastBuffData.Length + count];
  214. Array.Copy(lastBuffData, 0, newLastBuffData, 0, lastBuffData.Length);
  215. Array.Copy(buffData, 0, newLastBuffData, lastBuffData.Length, count);
  216. lastBuffData = newLastBuffData;
  217. break;
  218. }
  219. else if (lastBuffData != null) //处理半包情况
  220. {
  221. isBufferData = false;
  222. // LogTool.Log("修复半包" + lastCount + "__" + count + "___" +
  223. // (lastCount - lastBuffData.Length));
  224. sendType = lastSendType;
  225. data = new byte[lastCount];
  226. cdShort = lastCount - lastBuffData.Length;
  227. Array.Copy(lastBuffData, 0, data, 0, lastBuffData.Length);
  228. Array.Copy(buffData, currCount, data, lastBuffData.Length, cdShort);
  229. }
  230. SendDataType sendDataType = (SendDataType)sendType;
  231. if (sendDataType == SendDataType.Data)
  232. {
  233. using (MemoryStream compressedStream = new MemoryStream(data))
  234. {
  235. using (MemoryStream decompressedStream = new MemoryStream())
  236. {
  237. using (GZipStream gzipStream =
  238. new GZipStream(compressedStream, CompressionMode.Decompress))
  239. {
  240. gzipStream.CopyTo(decompressedStream);
  241. }
  242. data = decompressedStream.ToArray();
  243. }
  244. }
  245. }
  246. switch (sendDataType)
  247. {
  248. case SendDataType.ShakeHands:
  249. IsConnection = true;
  250. isAwaitReConnect = false;
  251. _cTask.SetResult();
  252. LogTool.Log("握手成功");
  253. break;
  254. case SendDataType.Data:
  255. // CombatSynchronizeResponsePack combatSynchronizeResponse =
  256. // CombatSynchronizeResponsePack.Parser.ParseFrom(data);
  257. // if (combatSynchronizeResponse == null)
  258. // {
  259. // LogTool.Error("错误的实例化战斗" + data.Length);
  260. // }
  261. // else
  262. // {
  263. // IsConnection = true;
  264. // isAwaitReConnect = false;
  265. // long t = System.DateTime.Now.Ticks;
  266. // // LogTool.Log("收包延迟" + (t - combatSynchronizeResponse.Time) / 10000);
  267. // // LogTool.Error("收到客户端消息" + combatSynchronizeRequest.CombatSynchronizeType);
  268. // client.AddCombatSynchronizeResponse(combatSynchronizeResponse);
  269. // }
  270. break;
  271. }
  272. currCount += cdShort;
  273. startIndex = currCount;
  274. }
  275. }
  276. catch (Exception e)
  277. {
  278. LogTool.Exception(e);
  279. // LogTool.Log("");
  280. }
  281. }
  282. catch (Exception e)
  283. {
  284. // LogTool.Log(e);
  285. break;
  286. }
  287. Thread.Sleep(1);
  288. }
  289. IsConnection = false;
  290. disconnect = true;
  291. LogTool.Log("服务器执行完毕");
  292. }
  293. public void SendToServer(SendDataType sendDataType, byte[] buffer)
  294. {
  295. byte[] mdata = null;
  296. // LogTool.Log("回复消息" + buffer.Length);
  297. mdata = new byte[buffer.Length + 5];
  298. mdata[0] = (byte)sendDataType;
  299. byte[] zcd = SocketTool.IntToByte(buffer.Length);
  300. mdata[1] = zcd[0];
  301. mdata[2] = zcd[1];
  302. mdata[3] = zcd[2];
  303. mdata[4] = zcd[3];
  304. Array.Copy(buffer, 0, mdata, 5, buffer.Length);
  305. try
  306. {
  307. socket.Send(mdata);
  308. }
  309. catch (Exception e)
  310. {
  311. LogTool.Exception(e);
  312. }
  313. }
  314. public void Finish()
  315. {
  316. isFinish = true;
  317. }
  318. public void Dispose()
  319. {
  320. socket?.Close();
  321. socket?.Dispose();
  322. socket = null;
  323. _udpClientThread = null;
  324. }
  325. }
  326. }