Last active
March 1, 2023 11:53
-
-
Save RevenantX/e251b28a62d7c8caa570d352cd007c90 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Net; | |
using System.Net.Sockets; | |
using LiteNetLib.Utils; | |
namespace Code.ExperimentalCode | |
{ | |
public class UdpNetWrapper | |
{ | |
class ClientData | |
{ | |
private const int ReceiveBufferSize = 1500; | |
private readonly Socket _tcpSocket; | |
private readonly Socket _udpSocket; | |
private readonly byte[] _tcpBuffer = new byte[ReceiveBufferSize * 2]; | |
private readonly byte[] _udpBuffer = new byte[ReceiveBufferSize]; | |
private int _bufferPos; | |
private EndPoint _udpEp; | |
private readonly IPEndPoint _serverEndPoint; | |
public ClientData(Socket tcpSocket, IPEndPoint udpBindPoint, int targetPort, IPEndPoint serverEndPoint) | |
{ | |
_serverEndPoint = serverEndPoint; | |
_tcpSocket = tcpSocket; | |
_udpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp) | |
{ | |
ReceiveBufferSize = BuffSize, | |
SendBufferSize = BuffSize | |
}; | |
_udpSocket.Bind(udpBindPoint); | |
if (targetPort != 0) //server | |
{ | |
_udpEp = new IPEndPoint(IPAddress.Loopback, targetPort); | |
_tcpSocket.BeginReceive(_tcpBuffer, 0, _tcpBuffer.Length, SocketFlags.None, AsyncTcpReceive, this); | |
} | |
else //client | |
{ | |
_udpEp = new IPEndPoint(IPAddress.Loopback, 0); | |
} | |
_udpSocket.BeginReceiveFrom(_udpBuffer, 2, _udpBuffer.Length - 2, SocketFlags.None, ref _udpEp, AsyncUdpReceive, this); | |
} | |
private void AsyncTcpReceive(IAsyncResult asyncResult) | |
{ | |
try | |
{ | |
int size = _tcpSocket.EndReceive(asyncResult); | |
if (size == 0) | |
{ | |
Close(); | |
return; | |
} | |
_bufferPos += size; | |
while (_bufferPos > 2) | |
{ | |
int packetSize = BitConverter.ToUInt16(_tcpBuffer, 0); | |
int totalSize = packetSize + 2; | |
if (_bufferPos < totalSize) | |
break; | |
_udpSocket.SendTo(_tcpBuffer, 2, packetSize, SocketFlags.None, _udpEp); | |
if(_bufferPos > totalSize) | |
Buffer.BlockCopy(_tcpBuffer, totalSize, _tcpBuffer, 0, _bufferPos - totalSize); | |
_bufferPos -= totalSize; | |
} | |
_tcpSocket.BeginReceive(_tcpBuffer, _bufferPos, _tcpBuffer.Length - _bufferPos, SocketFlags.None, AsyncTcpReceive, this); | |
} | |
catch (ObjectDisposedException) | |
{ | |
Close(); | |
} | |
catch | |
{ | |
// Debug.Log(e.ToString()); | |
Close(); | |
} | |
} | |
private void AsyncUdpReceive(IAsyncResult asyncResult) | |
{ | |
try | |
{ | |
int size = _udpSocket.EndReceiveFrom(asyncResult, ref _udpEp); | |
if (!_tcpSocket.Connected) | |
{ | |
_tcpSocket.Connect(_serverEndPoint); | |
_tcpSocket.BeginReceive(_tcpBuffer, 0, _tcpBuffer.Length, SocketFlags.None, AsyncTcpReceive, this); | |
} | |
FastBitConverter.GetBytes(_udpBuffer, 0, (ushort)size); | |
// _tcpSocket.Send(_udpBuffer, 0, size+2, SocketFlags.None); | |
var _tmp = new byte[ReceiveBufferSize * 2]; | |
_udpBuffer.CopyTo(_tmp, 0); | |
_tcpSocket.BeginSend(_tmp, 0, size+2, SocketFlags.None, ar => { }, null); | |
//Console.WriteLine($"AsyncUdpReceive: {size}, ep: {_udpEp}, SendTo: {cd.TcpSocket.RemoteEndPoint}"); | |
_udpSocket.BeginReceiveFrom(_udpBuffer, 2, _udpBuffer.Length - 2, SocketFlags.None, ref _udpEp, AsyncUdpReceive, this); | |
} | |
catch (ObjectDisposedException) | |
{ | |
Close(); | |
} | |
catch | |
{ | |
// Debug.Log(e.ToString()); | |
} | |
} | |
public void Close() | |
{ | |
_tcpSocket.Close(); | |
_udpSocket.Close(); | |
} | |
} | |
private readonly Socket _tcpSocket; | |
private const int BuffSize = 1024 * 1024; | |
private readonly int _targetPort; | |
//Client mode | |
public UdpNetWrapper(int listenPort, IPEndPoint serverEndPoint) | |
{ | |
_tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) | |
{ | |
ReceiveBufferSize = BuffSize, | |
SendBufferSize = BuffSize | |
}; | |
//_tcpSocket.Bind(new IPEndPoint(IPAddress.Any, 0)); | |
new ClientData(_tcpSocket, new IPEndPoint(IPAddress.Loopback, listenPort), 0, serverEndPoint); | |
} | |
//Server mode | |
public UdpNetWrapper(int listenPort, int targetPort) | |
{ | |
_targetPort = targetPort; | |
_tcpSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) | |
{ | |
ReceiveBufferSize = BuffSize, | |
SendBufferSize = BuffSize | |
}; | |
_tcpSocket.Bind(new IPEndPoint(IPAddress.Any, listenPort)); | |
_tcpSocket.Listen(1000); | |
_tcpSocket.BeginAccept(AsyncTcpAccept, _tcpSocket); | |
} | |
private void AsyncTcpAccept(IAsyncResult asyncResult) | |
{ | |
ClientData cd = null; | |
try | |
{ | |
Socket user = _tcpSocket.EndAccept(asyncResult); | |
cd = new ClientData(user, new IPEndPoint(IPAddress.Any, 0), _targetPort, null); | |
} | |
catch(Exception) | |
{ | |
if (cd != null) | |
{ | |
cd.Close(); | |
} | |
} | |
try | |
{ | |
_tcpSocket.BeginAccept(AsyncTcpAccept, _tcpSocket); | |
} | |
catch (Exception) | |
{ | |
//nothing | |
} | |
} | |
public void Close() | |
{ | |
_tcpSocket.Close(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment