I'm writing a game server using it's own protocol on top of TCP.
The packets are of the form varint packet_length followed by that amount of bytes.
To read a varint, I must read byte by byte. But Stream or NetworkStream does not provide a ReadByteAsync method, which means the task and therefore the thread will block if there is no data available from the socket yet. Of course I would wrap NetworkSteam with a BufferedStream but even BufferedStream's ReadByte uses synchronous Read to read to it's buffer. This will block.
This is how the server roughly looks like:
public static void Main(string[] args)
{
var listener = new TcpListener(new IPEndPoint(IPAddress.Any, 25000));
while (true)
{
var client = listener.AcceptTcpClientAsync().Result;
HandleClient(client).ContinueWith(t => {
if (t.IsFaulted)
{
Console.WriteLine(t.Exception);
}
});
}
}
public static async Task HandleClient(TcpClient client)
{
await Task.Yield();
while (true)
{
// read packet
// using ReadByte here would block if data is not available, which means I'm wasting a thread?
}
}
Why is ReadByteAsync not there? Or am I missing something?
Just use the already existing method ReadAsync, bending it in your favor:
private static async Task<byte> ReadByteAsync(Stream s)
{
byte[] buffer = new byte[1];
await s.ReadAsync(buffer, 0, 1);
return buffer[0];
}
Homework for ya: factor out the buffer into a class-level field so it doesn't get created each method call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With