I wrote a C# game server that usually has several hundred people connected to it, and based it on this example from Microsoft. The players are always sending data back and forth, and the connections are rarely idle. I have started wondering though: is every player connection launching its own Thread? Would it be better performance-wise if I recoded it to use 'Tasks/Await/etc' instead?
[EDIT] Is the way I'm calling Thread.Sleep() an appropriate way to throttle someone's connection? Or, instead of using Thread.Sleep(), should I have it launch a task with Task.Delay() that contains SendBytes()
public class Server
{
void Listen()
{
IPAddress IpAddr = IPAddress.Parse(ipv4_local);
IPEndPoint ipEnd = new IPEndPoint(IpAddr, port);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listener.Bind(ipEnd);
listener.Listen(5000);
while (true)
{
listener_allDone.Reset();
listener.BeginAccept(new AsyncCallback(AcceptConnection), listener);
listener_allDone.WaitOne();
}
}
void AcceptConnection(IAsyncResult ar)
{
listener_allDone.Set();
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
Player player = new Player(handler);
player.InitReceive();
}
}
And the player class, where Thread.Sleep() is used to throttle...
public class Player
{
public Socket socket;
public byte[] send_buffer = new byte[2048];
public byte[] receive_buffer = new byte[2048];
public Player(Socket socket)
{
this.socket = socket;
}
void SendBytes()
{
socket.BeginSend(send_buffer, 0, send_buffer.Length, SocketFlags.None, OnSendComplete, null);
}
void OnSendComplete(System.IAsyncResult iar)
{
int bytes_sent = socket.EndSend(iar);
if (MORE BYTES TO SEND)
{
Thread.Sleep(100); //THROTTLE
SendBytes();
}
}
public void InitReceive()
{
socket.BeginReceive(receive_buffer, 0, receive_buffer.Length, 0, new AsyncCallback(ReadCallback), this);
}
public void ReadCallback(IAsyncResult ar)
{
Player player = (Player)ar.AsyncState;
Socket socket = player.socket;
int bytesRead = socket.EndReceive(ar);
if (bytesRead != 0)
{
// READ BYTES...
// PROCESS DATA...
if (NEED TO SEND RESPONSE)
{
SendBytes();
}
socket.BeginReceive(player.receive_buffer, 0, player.receive_buffer.Length, 0, new AsyncCallback(ReadCallback), player);
}
}
}