I'm writing a websocket server using .NET's HttpListener
class.
Essentially, I've got a HandleListener()
function which wait for clients to connect and yield each client to HandleClient(WebSocket client)
. So I currently have:
private async void HandleListener()
{
try
{
while (listener != null && listener.IsListening)
{
HttpListenerContext listenerContext = await listener.GetContextAsync();
WebSocketContext webSocketContext = await listenerContext.AcceptWebSocketAsync(subProtocol: null);
WebSocket webSocket = webSocketContext.WebSocket;
clients.Add(webSocket);
await HandleClient(webSocket);
}
}
catch (HttpListenerException) { } // Got here probably because StopWSServer() was called
}
private async Task HandleClient(WebSocket client) { ... }
Problem is, I can't seem to process more then one client. It looks like the execution of HandleListener()
halts as long as the first client is connected.
I tried removing the await
from the call to HandleClient()
, but I get the "because this call is not awaited..." error. I can make HandleClient()
a async void
method, but this is not an event handler.
BTW, the reason that HandleClient()
is async Task
is because it's doing, all over in a loop until the listener is dead:
recieveResult = await client.ReceiveAsync(recievedBuffer, CancellationToken.None);
From what I understand, a fire-and-forget approach is bad overall, and I can't seem to achieve it with async-await implementation. But HandleClient()
is a fire-and-forget method, and I don't see any other way of achieving what I need.
EDIT: Added current implementation of HandleClient()
:
private async Task HandleClient(WebSocket client)
{
try
{
ArraySegment<byte> recievedBuffer = new ArraySegment<byte>(new byte[BUFFER_SIZE]);
while (listener != null && listener.IsListening && client.State == WebSocketState.Open)
{
WebSocketReceiveResult recieveResult;
using (var ms = new MemoryStream())
{
do
{
recieveResult = await client.ReceiveAsync(recievedBuffer, CancellationToken.None);
ms.Write(recievedBuffer.Array, recievedBuffer.Offset, recieveResult.Count);
}
while (!recieveResult.EndOfMessage);
switch (recieveResult.MessageType)
{
case WebSocketMessageType.Close:
RemoveClient(client, WebSocketCloseStatus.NormalClosure, string.Empty);
break;
case WebSocketMessageType.Binary:
RemoveClient(client, WebSocketCloseStatus.InvalidMessageType, "Cannot accept binary frame");
break;
case WebSocketMessageType.Text:
OnRecieve?.Invoke(client, System.Text.Encoding.UTF8.GetString(ms.ToArray()));
break;
}
}
}
}
catch (WebSocketException ex)
{
RemoveClient(client, WebSocketCloseStatus.InternalServerError, ex.Message);
}
}
it will do like that because you wrote code for it, my mean to say you wrote method as below.
In this method when it encounter
await
control will get return to orignal caller ,till you await part got completed and next call start after it.Check below image this how await and async works
If you just want fire and forget than try like this
which means dont wait for completion of task