Reputation: 153
I am trying to use the Web PubSub Service resource in Azure, and have created a basic client using ClientWebSocket. Everything is fine, it sits there waiting for something to come through, however, after 36 hours or so (take that time with a pinch of salt but its a fairly long time), it loses connection, and then when i try and connect again, i get the following error over and over again:
"The server returned status code '401' when status code '101' was expected."
This is sitting inside a Blazor app, and an instance of the client is sitting inside a singleton service that is always running. If i restart the blazor app, then it connects fine again. This is the client i have created:
public class AzurePubSubWebsocketClient
{
private readonly Uri _serverUri;
private CancellationTokenSource _cancellationTokenSource;
private bool _isRunning = false;
private object _runningLockObject = new object();
int reconnectDelaySeconds = 5; // Adjust the delay (in seconds) between reconnection attempts.
public event Action<string> OnLogMessage;
public event Action<string> OnMessageReceived;
public AzurePubSubWebsocketClient(Uri serverUri)
{
this._serverUri = serverUri;
}
public async Task ConnectAndReceiveMessages()
{
while (true)
{
try
{
OnLogMessage?.Invoke("Connecting to WebSocket...");
using (var clientWebSocket = new ClientWebSocket())
{
await clientWebSocket.ConnectAsync(_serverUri, CancellationToken.None);
OnLogMessage?.Invoke("Connected to the WebSocket server.");
lock (_runningLockObject)
{
_isRunning = true;
}
// Receive messages from the server in a loop.
byte[] receiveBuffer = new byte[4096];
WebSocketReceiveResult receiveResult;
while (clientWebSocket.State == WebSocketState.Open)
{
receiveResult = await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), CancellationToken.None);
if (receiveResult.MessageType == WebSocketMessageType.Text)
{
string message = Encoding.UTF8.GetString(receiveBuffer, 0, receiveResult.Count);
OnLogMessage?.Invoke($"Received message: {message}");
try
{
OnMessageReceived?.Invoke(message);
}
catch (Exception exception)
{
OnMessageReceived?.Invoke(exception.Message);
}
}
}
lock (_runningLockObject)
{
_isRunning = false;
}
}
}
catch (Exception ex)
{
lock (_runningLockObject)
{
_isRunning = false;
}
OnLogMessage?.Invoke($"Error: {ex.Message}");
}
// Reconnection delay to avoid frequent connection attempts.
OnLogMessage?.Invoke($"Connection lost. Retrying in {reconnectDelaySeconds} seconds...");
await Task.Delay(TimeSpan.FromSeconds(reconnectDelaySeconds));
}
}
public bool IsRunning()
{
lock (_runningLockObject)
{
return _isRunning;
}
}
}
The first time connection is lost, there is no Exception, it just comes out the while loop (though to be fair im not logging what the MessageType is) and then after that everytime it tries to connect i get that 401 error.
[03/08/23 11:18:16.104] Connection lost. Retrying in 5 seconds...
[03/08/23 11:18:21.103] Connecting to WebSocket...
[03/08/23 11:18:21.148] Error: The server returned status code '401' when status code '101' was expected.
[03/08/23 11:18:21.148] Connection lost. Retrying in 5 seconds...
[03/08/23 11:18:26.150] Connecting to WebSocket...
[03/08/23 11:18:26.163] Error: The server returned status code '401' when status code '101' was expected.
[03/08/23 11:18:26.163] Connection lost. Retrying in 5 seconds...
[03/08/23 11:18:31.166] Connecting to WebSocket...
[03/08/23 11:18:31.209] Error: The server returned status code '401' when status code '101' was expected.
[03/08/23 11:18:31.209] Connection lost. Retrying in 5 seconds...
[03/08/23 11:18:36.198] Connecting to WebSocket...
[03/08/23 11:18:36.256] Error: The server returned status code '401' when status code '101' was expected.
[03/08/23 11:18:36.256] Connection lost. Retrying in 5 seconds...
[03/08/23 11:18:41.263] Connecting to WebSocket...
Upvotes: 0
Views: 1152
Reputation: 3297
Error: The server returned status code '401' when status code '101' was expected.
public class AzurePubSubWebsocketClient
{
private readonly Uri _serverUri;
private bool _isRunning;
private readonly object _runningLockObject = new object();
public event Action<string> OnMessageReceived;
public event Action<string> OnLogMessage;
public AzurePubSubWebsocketClient(Uri serverUri)
{
_serverUri = serverUri;
}
public async Task ConnectAndReceiveMessages()
{
// Sample token for testing purposes (replace with your actual token)
string sampleToken = "YOUR_SAMPLE_TOKEN_HERE";
while (true)
{
try
{
OnLogMessage?.Invoke("Connecting to WebSocket...");
using (var clientWebSocket = new ClientWebSocket())
{
// Add the sample token to the headers
clientWebSocket.Options.SetRequestHeader("Authorization", $"Bearer {sampleToken}");
await clientWebSocket.ConnectAsync(_serverUri, CancellationToken.None);
OnLogMessage?.Invoke("Connected to the WebSocket server.");
lock (_runningLockObject)
{
_isRunning = true;
}
// Receive messages from the server in a loop.
byte[] receiveBuffer = new byte[4096];
WebSocketReceiveResult receiveResult;
while (clientWebSocket.State == WebSocketState.Open)
{
receiveResult = await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(receiveBuffer), CancellationToken.None);
if (receiveResult.MessageType == WebSocketMessageType.Text)
{
string message = Encoding.UTF8.GetString(receiveBuffer, 0, receiveResult.Count);
OnLogMessage?.Invoke($"Received message: {message}");
try
{
OnMessageReceived?.Invoke(message);
}
catch (Exception exception)
{
OnLogMessage?.Invoke(exception.Message);
}
}
}
lock (_runningLockObject)
{
_isRunning = false;
}
}
}
catch (Exception ex)
{
lock (_runningLockObject)
{
_isRunning = false;
}
OnLogMessage?.Invoke($"Error: {ex.Message}");
}
// Reconnection delay to avoid frequent connection attempts.
int reconnectDelaySeconds = 5; // Change this as needed
OnLogMessage?.Invoke($"Connection lost. Retrying in {reconnectDelaySeconds} seconds...");
await Task.Delay(TimeSpan.FromSeconds(reconnectDelaySeconds));
}
}
public bool IsRunning()
{
lock (_runningLockObject)
{
return _isRunning;
}
}
}
If the WebSocket is in another domain, then configure the CORS to allow requests from your client's domain.
Here I can see in monitoring metrics that which get the request from client server:
Upvotes: 0