| 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;        }    }}
 |