123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- using System;
- using System.Buffers;
- using System.IO;
- using System.IO.Compression;
- using System.Net;
- using System.Net.Sockets;
- using System.Net.Sockets.Kcp;
- using System.Threading;
- using Fort23.Core;
- using Fort23.UTool;
- namespace Core.KCPTool
- {
- public class KCPClient : IKcpCallback, IDisposable, IClientConnection
- {
- private Socket socket;
- private Thread _udpClientThread;
- public bool IsConnection { get; set; }
- public bool disconnect { get; set; }
- public long playerId;
- private byte[] buffer = new byte[2048];
- private byte[] sendBuffer = new byte[2048];
- private Thread _updateThread;
- private Thread _receiveThread;
- private IClient client;
- /// <summary>
- /// 上次心跳时间
- /// </summary>
- private long lasetGetHandshakeTime = 0;
- public SimpleSegManager.Kcp kcp
- {
- get { return _kcp; }
- }
- public IPEndPoint EndPoint { get; set; }
- private SimpleSegManager.Kcp _kcp;
- private bool isUpdate;
- public bool isAwaitReConnect { get; set; }
- private CTask _cTask;
- // private long _connectTime;
- public KCPClient()
- {
- }
- public async CTask Connect(IPEndPoint endPoint, long playerId, IClient client)
- {
- try
- {
- _cTask = CTask.Create(false);
- this.client = client;
- this.playerId = playerId;
- isUpdate = true;
- socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- socket.Connect(endPoint);
- _kcp = new SimpleSegManager.Kcp(0, this);
- kcp.NoDelay(1, 40, 2, 1);
- this.EndPoint = endPoint;
- _udpClientThread = new Thread(BeginRecv);
- _udpClientThread.Start();
- IsConnection = false;
- disconnect = false;
- // _connectTime = System.DateTime.Now.Ticks;
- byte[] data = SocketTool.LongToByte(playerId);
- socket.Send(data);
- // SendToServer(SendDataType.ShakeHands, data);
- _updateThread = new Thread(Update);
- _receiveThread = new Thread(ReceiveAsyncThread);
- _updateThread.Start();
- _receiveThread.Start();
- lasetGetHandshakeTime = 0;
- await _cTask;
- }
- catch (Exception e)
- {
- disconnect = true;
- LogTool.Exception(e);
- throw;
- }
- }
- public void ReConnect(IPEndPoint endPoint, int gameFrame)
- {
- // LogTool.Log("重新链接");
- // if (socket != null)
- // {
- // socket.Dispose();
- // socket = null;
- // }
- //
- // lasetGetHandshakeTime = 0;
- // // _udpClientThread = null;
- // Thread.Sleep(10);
- // socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
- // socket.Connect(endPoint);
- // this.EndPoint = endPoint;
- // byte[] data = SocketTool.LongToByte(playerId);
- // socket.Send(data);
- // // SendToServer(SendDataType.ShakeHands, data);
- // IsConnection = false;
- // disconnect = false;
- // 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);
- }
- public void Output(IMemoryOwner<byte> buffer, int avalidLength)
- {
- if (EndPoint == null || disconnect)
- {
- return;
- }
- var s = buffer.Memory.Span.Slice(0, avalidLength).ToArray();
- if (socket == null)
- {
- return;
- }
- try
- {
- socket.Send(s);
- }
- catch (Exception e)
- {
- // disconnect = true;
- // disconnect = true;
- // IsConnection = false;
- if (socket != null)
- {
- socket.Dispose();
- socket = null;
- }
- }
- buffer.Dispose();
- }
- public void SendToServer(SendDataType sendDataType, byte[] buffer)
- {
- byte[] sendBuff = new byte[buffer.Length + 1];
- sendBuff[0] = (byte)sendDataType;
- Array.Copy(buffer, 0, sendBuff, 1, buffer.Length);
- int c = kcp.Send(sendBuff.AsSpan().Slice(0, sendBuff.Length));
- }
- public void Finish()
- {
- }
- public byte[] ReceiveAsync()
- {
- var (buffer, avalidLength) = kcp.TryRecv();
- while (buffer == null)
- {
- Thread.Sleep(5);
- if (_udpClientThread == null)
- {
- return null;
- }
- (buffer, avalidLength) = kcp.TryRecv();
- }
- var s = buffer.Memory.Span.Slice(0, avalidLength).ToArray();
- return s;
- }
- private async void BeginRecv()
- {
- while (isUpdate)
- {
- try
- {
- if (socket == null)
- {
- Thread.Sleep(3);
- continue;
- }
- if (socket.Receive(buffer, SocketFlags.Peek) <= 0)
- {
- Thread.Sleep(3);
- continue;
- }
- int count = socket.Receive(buffer, SocketFlags.None);
- if (count <= 0)
- {
- Thread.Sleep(3);
- continue;
- }
- try
- {
- byte[] data = new byte[count];
- Array.Copy(buffer, 0, data, 0, data.Length);
- int ok = kcp.Input(data);
- }
- catch (Exception e)
- {
- LogTool.Exception(e);
- }
- }
- catch (Exception e)
- {
- LogTool.Log("链接断开");
- // socket.Dispose();
- socket = null;
- disconnect = true;
- IsConnection = false;
- }
- Thread.Sleep(3);
- }
- LogTool.Log("执行完成kcp_BeginRecv");
- }
- private void Update()
- {
- while (isUpdate)
- {
- try
- {
- kcp.Update(DateTimeOffset.UtcNow);
- if (IsConnection)
- {
- if (DateTime.Now.Ticks - lasetGetHandshakeTime > 70000000) //断开了链接
- {
- disconnect = true;
- IsConnection = false;
- return;
- }
- }
-
- Thread.Sleep(5);
- }
- catch (Exception e)
- {
- LogTool.Error(e);
- }
- }
- LogTool.Log("执行完成kcp_Update");
- }
- private void ReceiveAsyncThread()
- {
- while (isUpdate)
- {
- try
- {
- var res = ReceiveAsync();
- if (res == null)
- {
- Thread.Sleep(10);
- continue;
- }
- SendDataType sendDataType = (SendDataType)res[0];
- byte[] decompressedByte = null;
- if (sendDataType == SendDataType.Data)
- {
- byte[] jmData = new byte[res.Length - 1];
- Array.Copy(res, 1, jmData, 0, jmData.Length);
- using (MemoryStream compressedStream = new MemoryStream(jmData))
- {
- using (MemoryStream decompressedStream = new MemoryStream())
- {
- using (GZipStream gzipStream =
- new GZipStream(compressedStream, CompressionMode.Decompress))
- {
- gzipStream.CopyTo(decompressedStream);
- }
- decompressedByte = decompressedStream.ToArray();
- }
- }
- }
- else
- {
- decompressedByte = res;
- }
- switch (sendDataType)
- {
- case SendDataType.ShakeHands:
- byte[] playerData = new byte[8];
- playerData[0] = decompressedByte[1];
- playerData[1] = decompressedByte[2];
- playerData[2] = decompressedByte[3];
- playerData[3] = decompressedByte[4];
- playerData[4] = decompressedByte[5];
- playerData[5] = decompressedByte[6];
- playerData[6] = decompressedByte[7];
- playerData[7] = decompressedByte[8];
- long playerId = SocketTool.ByteToInt(playerData);
- if (playerId != this.playerId)
- {
- LogTool.Error("握手消息不对");
- }
- IsConnection = true;
- isAwaitReConnect = false;
- if (lasetGetHandshakeTime == 0)
- {
- lasetGetHandshakeTime = DateTime.Now.Ticks;
- }
- _cTask.SetResult();
- break;
- case SendDataType.Heartbeat:
- if (!IsConnection)
- {
- LogTool.Log("链接成功");
- }
- isAwaitReConnect = false;
- IsConnection = true;
- lasetGetHandshakeTime = DateTime.Now.Ticks;
- // LogTool.Log("收到心跳包");
- break;
- case SendDataType.Data:
- // CombatSynchronizeResponsePack combatSynchronizeResponse =
- // CombatSynchronizeResponsePack.Parser.ParseFrom(decompressedByte);
- // if (combatSynchronizeResponse == null)
- // {
- // LogTool.Error("错误的实例化战斗" + decompressedByte.Length);
- // }
- // else
- // {
- // //
- // long t = System.DateTime.Now.Ticks;
- // // = (int) ((t - lasetTime) / 10000);
- // // lasetTime = t;
- // if (!IsConnection)
- // {
- // LogTool.Log("链接成功");
- // }
- //
- // if (lasetGetHandshakeTime == 0)
- // {
- // lasetGetHandshakeTime = DateTime.Now.Ticks;
- // }
- //
- // isAwaitReConnect = false;
- // IsConnection = true;
- // // LogTool.Log("收包延迟" + (t - combatSynchronizeResponse.Time) / 10000);
- // client.AddCombatSynchronizeResponse(combatSynchronizeResponse);
- // }
- break;
- }
- // await Task.Delay(Random.Next(0,200));
- }
- catch (Exception e)
- {
- LogTool.Error(e);
- }
- }
- }
- public void Dispose()
- {
- isUpdate = false;
- // _udpClientThread?.Abort();
- _udpClientThread = null;
- socket?.Dispose();
- kcp?.Dispose();
- socket = null;
- _kcp = null;
- }
- }
- }
|