You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

173 lines
5.2 KiB

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