Reputation: 165
i developed a guessing game in c# using websockets and https calls. Each time the user is creating an instance of the console application to play, it connects with the server. (await webSocket.ConnectAsync(new Uri("ws://localhost:xxx"), CancellationToken.None);).
I have a websocketmiddlewear class to accept the websocket reqeust and a manager class where i handle the websockets requests. Everything works fine except when the user exit the console game. For example when i press "x" from the console (cmd) i get the following error
The remote party closed the WebSocket connection without completing the close handshake.
on the following line
WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
Why the code is not handling the error and how i can fix it?
ConnectionManagerService.cs
public async Task Receive(WebSocket socket)
{
var buffer = new byte[1024 * 4];
while (socket.State == WebSocketState.Open)
{
WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Text)
{
Console.WriteLine($"Receive->Text");
return;
}
else if (result.MessageType == WebSocketMessageType.Close)
{
string id = _sockets.FirstOrDefault(s => s.Value == socket).Key;
//Console.WriteLine($"Receive->Close on: " + id);
_sockets.TryRemove(id, out socket);
Console.WriteLine("Managed Connections: " + _sockets.Count.ToString());
await socket.CloseOutputAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
return;
}
}
}
WebsocketMiddleware.cs
}
public async Task Invoke(HttpContext context)
{
var isSocketRequest = context.WebSockets.IsWebSocketRequest;
if (isSocketRequest)
{
WebSocket socket = await context.WebSockets.AcceptWebSocketAsync();
_manager.AddSocket(socket);
await _manager.Receive(socket);
}
else
{
await _next(context);
}
}
Upvotes: 1
Views: 2303
Reputation: 9360
It happens because you are treating only the graceful connection disconnect.The client might just disconnect and you will get big ol
SocketIO Exception
in the middle of a read/write
operation.
Consider wrapping your Socket
operation(s) in a try-catch
and deal with them as you please.
public async Task Receive(WebSocket socket)
{
var buffer = new byte[1024 * 4];
try{
while (true)
{
WebSocketReceiveResult result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
if (result.MessageType == WebSocketMessageType.Text)
{
Console.WriteLine($"Receive->Text");
return;
}
else if (result.MessageType == WebSocketMessageType.Close)
{
string id = _sockets.FirstOrDefault(s => s.Value == socket).Key;
//Console.WriteLine($"Receive->Close on: " + id);
_sockets.TryRemove(id, out socket);
Console.WriteLine("Managed Connections: " + _sockets.Count.ToString());
await socket.CloseOutputAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
return;
}
}
} catch(Exception ex){ //not so graceful disconnect
_sockets.TryRemove(id, out socket);
//deal with closed connection
//maybe reconnect ?
}
}
Upvotes: 2