using System; using System.IO; using System.IO.Compression; using System.Net; using System.Net.Sockets; using System.Threading; using Fort23.Core; using Fort23.UTool; using Task = System.Threading.Tasks.Task; namespace Core.KCPTool { public class TCPClient : IClientConnection { private byte[] buffData = new byte[6553]; private Socket socket; public bool IsConnection { get; set; } public bool disconnect { get; set; } //记录半包数据 private bool isBufferData; private byte[] lastBuffData; private int lastCount; private byte lastSendType; //数据结束 //尾包 private byte[] weiBaoBuffData; private Thread _udpClientThread; private IClient client; private long playerId; private bool isFinish; public bool isAwaitReConnect { get; set; } private bool isStartConnect; private CTask _cTask; public bool serveError; public TCPClient() { } public async Task Connect(IPEndPoint endPoint, long playerId, IClient client) { if (isStartConnect) { return; } serveError = false; _cTask = CTask.Create(false); isStartConnect = true; this.client = client; this.playerId = playerId; try { socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); await socket.ConnectAsync(endPoint); isStartConnect = false; } catch (Exception e) { disconnect = true; LogTool.Exception(e); isStartConnect = false; serveError = true; return; } IsConnection = false; disconnect = false; _udpClientThread = new Thread(TheUpdate); _udpClientThread.Start(); byte[] data = SocketTool.LongToByte(playerId); SendToServer(SendDataType.ShakeHands, data); await _cTask; } /// /// 重新链接 /// public async void ReConnect(IPEndPoint endPoint, int gameFrame) { // if (isStartConnect) // { // return; // } // // if (socket != null) // { // socket.Dispose(); // socket = null; // } // // isStartConnect = true; // Thread.Sleep(10); // LogTool.Error("开始重新链接" + gameFrame); // // try // { // socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // await socket.ConnectAsync(endPoint); // isStartConnect = false; // } // catch (Exception e) // { // disconnect = true; // LogTool.Exception(e); // isStartConnect = false; // return; // } // // disconnect = false; // _udpClientThread = new Thread(TheUpdate); // _udpClientThread.Start(); // isAwaitReConnect = true; byte[] data = SocketTool.LongToByte(playerId); byte[] gameFrameByte = SocketTool.IntToByte(gameFrame); byte[] buffer = new byte[data.Length + gameFrameByte.Length]; Array.Copy(data, 0, buffer, 0, data.Length); Array.Copy(gameFrameByte, 0, buffer, data.Length, gameFrameByte.Length); SendToServer(SendDataType.GetGameFrameByte, buffer); } private void TheUpdate() { while (socket != null) { try { int count = socket.Receive(buffData); if (count <= 0) { Thread.Sleep(1); return; } // LogTool.Log("数据来了" + count); try { int currCount = 0; int startIndex = 0; // bool isEnd = false; while (currCount < count) { // isEnd = true; byte[] data = null; byte sendType = 0; int cdShort = 0; if (!isBufferData) { if (weiBaoBuffData != null) { int maxCount = 6553500; if (count + weiBaoBuffData.Length > maxCount) { maxCount = count + weiBaoBuffData.Length; } // LogTool.Log("修复包太短__" + count + "___" + weiBaoBuffData.Length); byte[] newBuff = new byte[maxCount]; Array.Copy(weiBaoBuffData, 0, newBuff, 0, weiBaoBuffData.Length); Array.Copy(buffData, 0, newBuff, weiBaoBuffData.Length, count); buffData = newBuff; count += weiBaoBuffData.Length; // LogTool.Log("修复包后太短__" + count); if (count < 6) { weiBaoBuffData = new byte[count]; // LogTool.Log("包太短222__" + count); Array.Copy(buffData, currCount, weiBaoBuffData, 0, count); break; } else { weiBaoBuffData = null; } } else { if (count - currCount < 5) { weiBaoBuffData = new byte[count]; // LogTool.Log("包太短__" + count); Array.Copy(buffData, currCount, weiBaoBuffData, 0, count); break; } } } if (!isBufferData) { sendType = buffData[currCount]; currCount++; byte[] dataBuffLanl = new byte[4]; dataBuffLanl[0] = buffData[currCount]; currCount++; dataBuffLanl[1] = buffData[currCount]; currCount++; dataBuffLanl[2] = buffData[currCount]; currCount++; dataBuffLanl[3] = buffData[currCount]; currCount++; cdShort = (SocketTool.ByteToInt(dataBuffLanl)); // LogTool.Log("数据到来" + cdShort + "__" + count + "_" + sendType); if ((currCount + cdShort) > count) //处理半包情况 { lastBuffData = new byte[count - currCount]; lastCount = cdShort; lastSendType = sendType; Array.Copy(buffData, currCount, lastBuffData, 0, lastBuffData.Length); // LogTool.Log("数据只有一半" + count + "__" + currCount + "___" + cdShort); isBufferData = true; break; } else { // LogTool.Log(currCount + "_收到长度:" + cdShort + "_Max" + count); data = new byte[cdShort]; Array.Copy(buffData, currCount, data, 0, data.Length); } } else if (lastCount - lastBuffData.Length > count) { // LogTool.Log("数据只有一半的一半" + count + "__" + lastCount + "___" + lastBuffData.Length); byte[] newLastBuffData = new byte[lastBuffData.Length + count]; Array.Copy(lastBuffData, 0, newLastBuffData, 0, lastBuffData.Length); Array.Copy(buffData, 0, newLastBuffData, lastBuffData.Length, count); lastBuffData = newLastBuffData; break; } else if (lastBuffData != null) //处理半包情况 { isBufferData = false; // LogTool.Log("修复半包" + lastCount + "__" + count + "___" + // (lastCount - lastBuffData.Length)); sendType = lastSendType; data = new byte[lastCount]; cdShort = lastCount - lastBuffData.Length; Array.Copy(lastBuffData, 0, data, 0, lastBuffData.Length); Array.Copy(buffData, currCount, data, lastBuffData.Length, cdShort); } SendDataType sendDataType = (SendDataType)sendType; if (sendDataType == SendDataType.Data) { using (MemoryStream compressedStream = new MemoryStream(data)) { using (MemoryStream decompressedStream = new MemoryStream()) { using (GZipStream gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress)) { gzipStream.CopyTo(decompressedStream); } data = decompressedStream.ToArray(); } } } switch (sendDataType) { case SendDataType.ShakeHands: IsConnection = true; isAwaitReConnect = false; _cTask.SetResult(); LogTool.Log("握手成功"); break; case SendDataType.Data: // CombatSynchronizeResponsePack combatSynchronizeResponse = // CombatSynchronizeResponsePack.Parser.ParseFrom(data); // if (combatSynchronizeResponse == null) // { // LogTool.Error("错误的实例化战斗" + data.Length); // } // else // { // IsConnection = true; // isAwaitReConnect = false; // long t = System.DateTime.Now.Ticks; // // LogTool.Log("收包延迟" + (t - combatSynchronizeResponse.Time) / 10000); // // LogTool.Error("收到客户端消息" + combatSynchronizeRequest.CombatSynchronizeType); // client.AddCombatSynchronizeResponse(combatSynchronizeResponse); // } break; } currCount += cdShort; startIndex = currCount; } } catch (Exception e) { LogTool.Exception(e); // LogTool.Log(""); } } catch (Exception e) { // LogTool.Log(e); break; } Thread.Sleep(1); } IsConnection = false; disconnect = true; LogTool.Log("服务器执行完毕"); } public void SendToServer(SendDataType sendDataType, byte[] buffer) { byte[] mdata = null; // LogTool.Log("回复消息" + buffer.Length); mdata = new byte[buffer.Length + 5]; mdata[0] = (byte)sendDataType; byte[] zcd = SocketTool.IntToByte(buffer.Length); mdata[1] = zcd[0]; mdata[2] = zcd[1]; mdata[3] = zcd[2]; mdata[4] = zcd[3]; Array.Copy(buffer, 0, mdata, 5, buffer.Length); try { socket.Send(mdata); } catch (Exception e) { LogTool.Exception(e); } } public void Finish() { isFinish = true; } public void Dispose() { socket?.Close(); socket?.Dispose(); socket = null; _udpClientThread = null; } } }