I´m starting in the world of TCP Asynchronous
servers, searching a way to handle several connections at the same time I found out that BeginAcceptTcpClient
could be a solution.
I´ve found two possible ways to use BeginAcceptTcpClient
at the start of the server to receive connections. My question would be: what´s the difference between those two and which one would be thread safe (or if both are).
FIRST WAY
Calling BeginAcceptTcpClient
inside the callback.
static TcpListener socket = new TcpListener(IPAddress.Any, 4444);
public static void InitNetwork()
{
socket.Start();
socket.BeginAcceptTcpClient(new AsyncCallback(OnClientConnect), null);
}
private static void OnClientConnect(IAsyncResult ar)
{
TcpClient newclient = socket.EndAcceptTcpClient(ar);
socket.BeginAcceptTcpClient(new AsyncCallback (OnClientConnect), null); // Call the Callback again to continue listening
HandleClient.CreateConnection(newclient); //Do stuff with the client recieved
}
SECOND WAY
Using AutoResetEvent
.
static TcpListener socket = new TcpListener(IPAddress.Any, 4444);
private AutoResetEvent connectionWaitHandle = new AutoResetEvent(false);
public static void InitNetwork()
{
socket.Start();
while(true)
{
socket.BeginAcceptTcpClient(new AsyncCallback(OnClientConnect), null);
connectionWaitHandle.WaitOne(); // Wait until a client has begun handling an event
connectionWaitHandle.Reset(); // Reset wait handle or the loop goes as fast as it can (after first request)
}
}
private static void OnClientConnect(IAsyncResult ar)
{
TcpClient newclient = socket.EndAcceptTcpClient(ar);
connectionWaitHandle.Set(); //Inform the main thread this connection is now handled
HandleClient.CreateConnection(newclient); //Do stuff with the client recieved
}
I´m searching the correct way to handle multiple connections (been thread safe). I appreciate any answer.
I prefer AcceptTcpClientAsync
. It's simpler than BeginAcceptTcpClient
and still asynchronous.
public async Task InitNetwork()
{
while( true )
{
TcpClient newclient = await socket.AcceptTcpClientAsync();
Task.Run( () => HandleClient.CreateConnection( newclient ) );
}
}
Internally, AcceptTcpClientAsync
use Task.Factory.FromAsync
to wrap BeginAcceptTcpClient
and EndAcceptTcpClient
into a Task object.
public Task<TcpClient> AcceptTcpClientAsync()
{
return Task<TcpClient>.Factory.FromAsync(BeginAcceptTcpClient, EndAcceptTcpClient, null);
}