using System; using System.Net; using System.Net.Sockets; using UnityEngine; namespace Networking.Architecture { public class TcpManager { private const int DataBufferSize = 4096; private byte[] _receiveBuffer; private Packet _receivedData; private NetworkStream _stream; public TcpClient Socket; public bool IsConnected => Socket != null; public void Connect() { Socket = new TcpClient { ReceiveBufferSize = DataBufferSize, SendBufferSize = DataBufferSize }; _receiveBuffer = new byte[DataBufferSize]; Socket.BeginConnect(Client.Instance.ip, Client.Instance.port, ConnectCallback, Socket); } private void ConnectCallback(IAsyncResult result) { Socket.EndConnect(result); if (!Socket.Connected) return; _stream = Socket.GetStream(); _receivedData = new Packet(); _stream.BeginRead(_receiveBuffer, 0, DataBufferSize, ReceiveCallback, null); } // ReSharper disable Unity.PerformanceAnalysis public void SendData(Packet packet) { try { if (Socket != null) _stream.BeginWrite(packet.ToArray(), 0, packet.Length(), null, null); } catch (Exception ex) { Debug.Log($"Error sending data to server via TCP: {ex}"); } } private void ReceiveCallback(IAsyncResult result) { try { var byteLength = _stream.EndRead(result); if (byteLength <= 0) { Client.Instance.Disconnect(); return; } var data = new byte[byteLength]; Array.Copy(_receiveBuffer, data, byteLength); _receivedData.Reset(HandleData(data)); _stream.BeginRead(_receiveBuffer, 0, DataBufferSize, ReceiveCallback, null); } catch { Disconnect(); } } private bool HandleData(byte[] data) { var packetLength = 0; _receivedData.SetBytes(data); if (_receivedData.UnreadLength() >= 4) { packetLength = _receivedData.ReadInt(); if (packetLength <= 0) return true; } while (packetLength > 0 && packetLength <= _receivedData.UnreadLength()) { var packetBytes = _receivedData.ReadBytes(packetLength); ThreadManager.ExecuteOnMainThread(() => ReadPacket.Read(packetBytes)); packetLength = 0; if (_receivedData.UnreadLength() < 4) continue; packetLength = _receivedData.ReadInt(); if (packetLength <= 0) return true; } return packetLength <= 1; } private void Disconnect() { Client.Instance.Disconnect(); _stream = null; _receivedData = null; _receiveBuffer = null; Socket = null; } } public class UdpManager { private IPEndPoint _endPoint; public UdpClient Socket; public UdpManager() { _endPoint = new IPEndPoint(IPAddress.Parse(Client.Instance.ip), Client.Instance.port); } public void Connect(int localPort) { Socket = new UdpClient(localPort); Socket.Connect(_endPoint); Socket.BeginReceive(ReceiveCallback, null); using var packet = new Packet(); SendData(packet); } public void SendData(Packet packet) { try { packet.InsertInt(Client.Instance.Id); Socket?.BeginSend(packet.ToArray(), packet.Length(), null, null); } catch (Exception ex) { Debug.Log($"Error sending data to server via UDP: {ex}"); } } private void ReceiveCallback(IAsyncResult result) { try { var data = Socket.EndReceive(result, ref _endPoint); Socket.BeginReceive(ReceiveCallback, null); if (data.Length < 4) { Client.Instance.Disconnect(); return; } HandleData(data); } catch { Disconnect(); } } private static void HandleData(byte[] data) { using (var packet = new Packet(data)) { var packetLength = packet.ReadInt(); data = packet.ReadBytes(packetLength); } ThreadManager.ExecuteOnMainThread(() => ReadPacket.Read(data)); } private void Disconnect() { Client.Instance.Disconnect(); Socket = null; _endPoint = null; } } internal static class ReadPacket { public static void Read(byte[] data){ using var packet = new Packet(data); var packetTypeId = packet.ReadInt(); var packetActionId = packet.ReadInt(); Client.PacketHandlers[packetTypeId][packetActionId](packet); } } }