Reputation: 1
I'm using the System.Net.WebSockets.ClientWebSocket
class in C# on .NET 6.0.
I have a thread that will poll this ClientWebSocket repeatedly by calling a function.
poll_thread = new Thread(poll);
poll_thread.Start();
The poll functions looks as follows:
private async void poll() {
while (true) {
// Wait 16 ms (1/60 of a second) before making another polling attempt.
Thread.Sleep(16);
switch (web_socket.State) {
case WebSocketState.Open: {
if (socket_connected == false) { socket_connected = true; }
try {
// RecieveAsync automatically polls and recieves the packet.
Memory<Byte> memory = new Memory<Byte>(new Byte[1024]);
Console.WriteLine("Awaiting started");
ValueWebSocketReceiveResult result = await web_socket.ReceiveAsync(memory, CancellationToken.None);
Console.WriteLine("Awaiting ended");
// Only attempt deserialization if a packet was recieved, aka the buffer is not empty.
if (result.Count != 0) {
deserialize_event(memory.Slice(0, result.Count).ToArray());
}
} catch (Exception exception) {
Console.WriteLine("Pusher polling error: " + exception.ToString());
}
} break;
case WebSocketState.Closed: {
connection_closed(web_socket.CloseStatus);
} break;
}
}
}
It's supposed to keep repeatedly polling the websocket.
The console output
As shown by the console output, after the first time it receives data, and attempts to poll again, the ValueWebSocketReceiveResult result = await web_socket.ReceiveAsync(memory, CancellationToken.None);
never actually finishes awaiting.
If the program is left running, eventually it raises an exception on that line that reads
System.Net.WebSockets.WebSocketException: 'The remote party closed the WebSocket connection without completing the close handshake.'
I do not understand why my implementation does not work, as it is a implementation ported from Godot Engine's WebSocketPeer
The GDScript implementation looks similar to the C# implementation.
func poll() -> void:
socket.poll()
match socket.get_ready_state():
WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
if not socket_connected:
socket_connected = true
call(&"emit_signal", &"connection_established")
var packet: PackedByteArray = socket.get_packet()
print(packet.size())
handle_event(packet)
WebSocketPeer.STATE_CLOSING:
# Keep polling to achieve proper close.
return
WebSocketPeer.STATE_CLOSED:
socket_connected = false
call(&"emit_signal", &"connection_closed", socket.get_close_code())
This version works perfectly as intended, it receives all of the packets of information as it should, connecting with the same configuration, but the point of this project is to not use the Godot Engine inside it, so this is one thing being ported.
Upvotes: 0
Views: 66
Reputation: 73
Handling for WebSocketState.CloseSent and WebSocketState.CloseReceived occurs during the closing process of a WebSocket connection. To ensure that the WebSocket is fully closed, you should keep polling until the WebSocket reaches the Closed state. Use ClientWebSocket.CloseOutputAsync instead of CloseAsync to indicate that no more output will be sent from the client. This graceful approach allows you to respond appropriately to the WebSocket close event and ensure proper closure of the connection.
Upvotes: 1