#if COMBAT_SERVER using System; using System.Buffers; using System.Collections.Generic; using System.IO.Compression; using System.Net; using System.Net.Sockets; using System.Net.Sockets.Kcp; using System.Threading; using Com.Fort23.Protocol.Protobuf; using Fort23.UTool; using Utility; namespace Core.KCPTool { public class KCPServer : IServer { private Socket socket; private Thread _udpClientThread; private byte[] buffer = new byte[2048]; private ArraySegment ArraySegment; public Map KcpServerConnections = new Map(); private List CombatSynchronizeRequests = new List(); // private List awaitConnections = new List(); private IServerManager iServerManager; private Queue _sendDataBuffers = new Queue(); private long lasetSendTime = 0; public KCPServer(int port, IServerManager iServerManager) { this.iServerManager = iServerManager; LogTool.Log("创建UDP链接端口"+port+"__"); socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); socket.Bind(new IPEndPoint(IPAddress.Any, port)); ArraySegment = new ArraySegment(buffer); _udpClientThread = new Thread(BeginRecv); _udpClientThread.Start(); } public void SocketSendTo(byte[] buffer, EndPoint endPoint) { // if (_sendDataBuffers.Count > 0) { // LogTool.Log("发送消息:"+endPoint.GetHashCode()); SendDataBuffer sendDataBuffer = new SendDataBuffer(); sendDataBuffer.buffer = buffer; sendDataBuffer.endPoint = endPoint; _sendDataBuffers.Enqueue(sendDataBuffer); } // else // { // SocketSendToForBuffer(buffer, endPoint); // } } private void SocketSendToForBuffer(byte[] buffer, EndPoint endPoint) { socket.SendTo(buffer, endPoint); } private byte[] AssembleData(SendDataType sendDataType, byte[] buffer) { byte[] sendBuff = new byte[buffer.Length + 1]; sendBuff[0] = (byte)sendDataType; Array.Copy(buffer, 0, sendBuff, 1, buffer.Length); return sendBuff; } public bool SendToPlayer(SendDataType sendDataType, CombatSynchronizeType combatSynchronizeType, byte[] buffer, long playerId) { if (KcpServerConnections.Count <= 0) { return true; } byte[] sendBuff = AssembleData(sendDataType, buffer); bool isOk = false; lock (KcpServerConnections) { for (KcpServerConnections.Begin(); KcpServerConnections.Next();) { if (KcpServerConnections.Value.isConnected) { isOk = true; } if (playerId != -1 && KcpServerConnections.Value.playerId != playerId) { continue; } KcpServerConnections.Value.SendData(sendBuff, sendBuff.Length); } } return isOk; } public void AddCombatSynchronizeRequest(CombatSynchronizeRequest combatSynchronizeRequest) { lock (CombatSynchronizeRequests) { CombatSynchronizeRequests.Add(combatSynchronizeRequest); } } public CombatSynchronizeRequest[] GetCombatSynchronizeRequest(bool isClear) { if (CombatSynchronizeRequests.Count <= 0) { return null; } lock (CombatSynchronizeRequests) { CombatSynchronizeRequest[] allData = CombatSynchronizeRequests.ToArray(); CombatSynchronizeRequests.Clear(); return allData; } } public bool UpdateKCP() { bool isConnected = false; if (_sendDataBuffers.TryDequeue(out SendDataBuffer sendDataBuffer)) { SocketSendToForBuffer(sendDataBuffer.buffer, sendDataBuffer.endPoint); } long currTime = DateTime.Now.Ticks; if (currTime - lasetSendTime > 50000000) { lasetSendTime = currTime; SendToPlayer(SendDataType.Heartbeat, CombatSynchronizeType.PrepareStart, new byte[1], -1); } lock (KcpServerConnections) { for (KcpServerConnections.Begin(); KcpServerConnections.Next();) { if (KcpServerConnections.Value.isConnected) { isConnected = true; KcpServerConnections.Value.Update(); } } } // lock (awaitConnections) // { // for (int i = 0; i < awaitConnections.Count; i++) // { // awaitConnections[i].Update(); // } // } return isConnected; } public void RecvKCP() { lock (KcpServerConnections) { for (KcpServerConnections.Begin(); KcpServerConnections.Next();) { if (KcpServerConnections.Value.isConnected) { KcpServerConnections.Value.ReceiveAsync(); } } } // lock (awaitConnections) // { // for (int i = 0; i < awaitConnections.Count; i++) // { // awaitConnections[i].ReceiveAsync(); // } // } } private async void BeginRecv() { while (_udpClientThread != null) { EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0); try { SocketReceiveFromResult receiveFromResult = await socket.ReceiveFromAsync(ArraySegment, SocketFlags.None, newClientEP); if (receiveFromResult.ReceivedBytes <= 0) { Thread.Sleep(10); continue; } newClientEP = receiveFromResult.RemoteEndPoint; byte[] data = new byte[receiveFromResult.ReceivedBytes]; Array.Copy(buffer, 0, data, 0, data.Length); if (receiveFromResult.ReceivedBytes == 8) //链接到了 { long playerId = SocketTool.ByteToLong(data); CreateNewConnections(newClientEP, playerId); continue; } else { IServerConnection kcpServerConnection = GetConnection(newClientEP.GetHashCode()); if (kcpServerConnection == null) { LogTool.Error("没有找到对应的客户端链接"); } else { int ok = kcpServerConnection.Input(data); } } } catch (Exception e) { // SocketException socketException = e as SocketException; // if (socketException.ErrorCode == 10054) // { // IServerConnection kcpServerConnection = GetConnection(newClientEP.GetHashCode()); // if (kcpServerConnection != null) //链接已经断开 // { // kcpServerConnection.isConnected = false; // } // } LogTool.Error(e); Thread.Sleep(10); // socket.Disconnect(); } } } public void RemovePlayer(long playerId) { lock (KcpServerConnections) { KcpServerConnections.Remove(playerId); } } public IServerConnection GetConnection(long playerId) { lock (KcpServerConnections) { for (KcpServerConnections.Begin(); KcpServerConnections.Next();) { if (playerId != -1 && KcpServerConnections.Value.playerId != playerId) { continue; } return KcpServerConnections.Value; } } return null; } public IServerConnection GetConnection(int connectionId) { lock (KcpServerConnections) { for (KcpServerConnections.Begin(); KcpServerConnections.Next();) { if (connectionId != -1 && KcpServerConnections.Value.connectionID != connectionId) { continue; } return KcpServerConnections.Value; } } return null; } public void RemoveServerConnection(long playerId) { lock (KcpServerConnections) { if (KcpServerConnections.TryGetValue(playerId, out IServerConnection serverConnection)) { LogTool.Log("移除成功UDP" + playerId); serverConnection.Dispose(); KcpServerConnections.Remove(playerId); } } } public void ConnectionUpdate() { if (socket != null) { try { UpdateKCP(); RecvKCP(); } catch (Exception e) { LogTool.Exception(e); } } } public async void SendGameFrame(int gameFrame, IServerConnection kcpServerConnection) { // if (gameFrame > 0) { LogTool.Log("重传数据开始" + gameFrame); int maxCount = iServerManager.GetSendBufferSize(); for (int i = gameFrame; i < maxCount; i++) { byte[] _sendBufferdata = iServerManager.GetSendBuffer(i); if (_sendBufferdata != null) { _sendBufferdata = AssembleData(SendDataType.Data, _sendBufferdata); kcpServerConnection.SendData(_sendBufferdata, _sendBufferdata.Length); await System.Threading.Tasks.Task.Delay(1); } } } } public void AddServerConnection(long playerId, int gameFrame, IServerConnection kcpServerConnection) { lock (KcpServerConnections) { RemoveServerConnection(playerId); iServerManager.AddServerConnection(this, kcpServerConnection); KcpServerConnections.Add(playerId, kcpServerConnection); LogTool.Log("握手成功UDP" + playerId); iServerManager.AddServerConnection(this, kcpServerConnection); byte[] data = SocketTool.LongToByte(playerId); SendToPlayer(SendDataType.ShakeHands, CombatSynchronizeType.PrepareStart, data, playerId); } // lock (awaitConnections) // { // awaitConnections.Remove(kcpServerConnection); // } } public IServerConnection CreateNewConnections(EndPoint newClientEP, long playerId) { // int code = newClientEP.GetHashCode(); KCPServerConnection kcpServerConnection = new KCPServerConnection(this, (IPEndPoint)newClientEP); kcpServerConnection.playerId = playerId; kcpServerConnection.connectionID = newClientEP.GetHashCode(); LogTool.Log("创建新的链接UDP" + newClientEP); AddServerConnection(playerId, 0, kcpServerConnection); return kcpServerConnection; } public void Dispose() { _udpClientThread = null; socket?.Dispose(); socket = null; } } } #endif