我正在使用 .NET 的HttpListener
类编写一个 websocket 服务器。
本质上,我有一个HandleListener()
等待客户端连接并将每个客户端生成到HandleClient(WebSocket client)
. 所以我目前有:
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) { ... }
问题是,我似乎无法处理一个以上的客户。HandleListener()
只要连接了第一个客户端,就好像执行暂停。
我尝试await
从对 的调用中删除HandleClient()
,但我收到“因为不等待此调用...”错误。我可以制作HandleClient()
一个async void
方法,但这不是一个事件处理程序。
顺便说一句,这HandleClient()
是async Task
因为它在循环中一直在做,直到侦听器死了:
recieveResult = await client.ReceiveAsync(recievedBuffer, CancellationToken.None);
据我了解,一劳永逸的方法总体上是不好的,我似乎无法通过 async-await 实现来实现它。但这HandleClient()
是一种即发即弃的方法,我看不到任何其他方法可以实现我所需要的。
编辑:添加了当前的实现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);
}
}