Problem
So I’m writing a game emulator and would like some advice after finishing the networking. It is designed to accept multiple connections, and process messages from all of them.
Here is just a brief introduction to the packets and how they are structured. [lengthOfString:short][stringEncodedInUtf8:Byte[]]
Let’s start with the NetworkHandler – this class is responsible for accepting new connections and storing them in the collection.
public class NetworkHandler : IDisposable
{
private readonly TcpListener _listener;
private readonly IList<NetworkClient> _clients;
private readonly ClientPacketHandler _packetHandler;
public NetworkHandler(TcpListener listener, IList<NetworkClient> clients, ClientPacketHandler packetHandler)
{
_listener = listener;
_clients = clients;
_packetHandler = packetHandler;
}
public void StartListener()
{
_listener.Start();
}
public async Task ListenAsync()
{
while (true)
{
var tcpClient = await _listener.AcceptTcpClientAsync();
var networkClient = new NetworkClient(tcpClient, _packetHandler);
_clients.Add(networkClient);
networkClient.StartReceiving();
}
}
public void Dispose()
{
foreach (var client in _clients)
{
client.Dispose();
}
_listener.Stop();
}
}
Then we have the NetworkClient, I made this so NetworkHandler could stay small and to follow SRP – This class handles incoming data from the individual connection (client).
public class NetworkClient
{
private readonly TcpClient _tcpClient;
private readonly NetworkStream _networkStream;
private readonly ClientPacketHandler _packetHandler;
public NetworkClient(TcpClient tcpClient, ClientPacketHandler packetHandler)
{
_tcpClient = tcpClient;
_networkStream = tcpClient.GetStream();
_packetHandler = packetHandler;
}
public void StartReceiving()
{
Task.Run(ProcessDataAsync);
}
private async Task ProcessDataAsync()
{
while (true)
{
using var br = new BinaryReader(new MemoryStream(await GetBinaryDataAsync()));
var messageLength = BinaryPrimitives.ReadInt32BigEndian(br.ReadBytes(4));
var packetData = br.ReadBytes(messageLength);
using var br2 = new BinaryReader(new MemoryStream(packetData));
var packetId = BinaryPrimitives.ReadInt16BigEndian(br2.ReadBytes(2));
if (packetId == 26979)
{
await WriteToStreamAsync(Encoding.Default.GetBytes("<?xml version="1.0""?>
Solution
rn<
!DOCTYPE cross-domain-policy SYSTEM ""/xml/dtds/cross-domain-policy.dtd"">
rn<
cross-domain-policy>
rn<