C
C#•6mo ago
Alex

Web sockets management

Hello! I don't understand how to hold a connection with client and how to detect when it was closed by client and remove it from list. I have route where users can subscribe to notification /notifications/sub. There I accept web socket and add it to dictionary, id is assigned to each web socket. Then I do the "while" loop because otherwise the connection closes immediately. Also I have a problem that if I close browsers is not removed from dictionary that I use to send messages? Is there a way to solve these problems?
[HttpGet("sub")]
public async Task Subscribe() {
if (HttpContext.WebSockets.IsWebSocketRequest) {
using WebSocket ws = await HttpContext.WebSockets.AcceptWebSocketAsync();

string key = _socketManagerService.AddSocket(ws);

await _socketManagerService.SendAsync(
key, new WebSocketMessage{
MessageType = MessageType.ConnectionEvent,
Data = new WebSocketMessageData{
Topic = "Connection",
Payload = $"Connection established {DateTime.UtcNow}"}});

_logger.LogInformation($"New connection: {key} - {DateTime.UtcNow}");

while (ws.State == WebSocketState.Open) {
}
await _socketManagerService.RemoveSocketAsync(key);
_logger.LogInformation($"Connection closed {key} - {DateTime.UtcNow}");
// var socketFinishedTcs = new TaskCompletionSource<object>();
// await socketFinishedTcs.Task;
} else {
throw new BadRequestException("Only web socket connections");
}
}
[HttpGet("sub")]
public async Task Subscribe() {
if (HttpContext.WebSockets.IsWebSocketRequest) {
using WebSocket ws = await HttpContext.WebSockets.AcceptWebSocketAsync();

string key = _socketManagerService.AddSocket(ws);

await _socketManagerService.SendAsync(
key, new WebSocketMessage{
MessageType = MessageType.ConnectionEvent,
Data = new WebSocketMessageData{
Topic = "Connection",
Payload = $"Connection established {DateTime.UtcNow}"}});

_logger.LogInformation($"New connection: {key} - {DateTime.UtcNow}");

while (ws.State == WebSocketState.Open) {
}
await _socketManagerService.RemoveSocketAsync(key);
_logger.LogInformation($"Connection closed {key} - {DateTime.UtcNow}");
// var socketFinishedTcs = new TaskCompletionSource<object>();
// await socketFinishedTcs.Task;
} else {
throw new BadRequestException("Only web socket connections");
}
}
14 Replies
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
I made infinite loop temporary because otherwise the connection with client closes immediately. This is my WebSocketManagerService. I store tasks in dictionary, but I don't know what to do next and how can I await for them. I also tried to await for the Task inside Subscribe method, you can see the commented part, but I couldn't connect from client WebSocketManagerService: https://pastebin.com/98d5UzET
Pastebin
public class WebSocketManagerService : IWebSocketManagerService{ ...
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
ok I think now it shows that client is connected with tcs, but how can I detect when user is disconnected without loop?
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
yes, I have this part
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
yes, maybe I had problem with React that it couldn't connect to ws after a replaced loop with await tsc. I'm right now trying to see the ws ids I have in my dictionary to see if they actually removed after client disconnects (or if it even detects it)
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
I thought it will be easier to use web sockets because SignalR has hubs and etc. Is it better to use SignalR? I have never used web sockets, signalR or sse, so I decided to start with something that doesn't look complex
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
I added code to remove web socket from dictionary if the state is not open, but I still can see them in my dictionary? I checked that ws should close automatically if there isn't connection to client. or does it throw an exception and should I put code it try catch?
public async Task SendAsync(string key, WebSocketMessage message)
{
WebSocket? ws = GetByKey(key);

if (ws == null) return;

if (ws.State != WebSocketState.Open)
{
_sockets.Remove(key, out _);
return;
}

await SendMessageAsync(ws, message);
}
public async Task SendAsync(string key, WebSocketMessage message)
{
WebSocket? ws = GetByKey(key);

if (ws == null) return;

if (ws.State != WebSocketState.Open)
{
_sockets.Remove(key, out _);
return;
}

await SendMessageAsync(ws, message);
}
Unknown User
Unknown User•6mo ago
Message Not Public
Sign In & Join Server To View
Alex
Alex•6mo ago
yes it's late, thank you for help, I'll try to fix it tomorrow 😀 I've tried signalR and decided to use it for my project, it looks easy to manage than websockets. Also if it's possible can I ask you a question about react?
Want results from more Discord servers?
Add your server