public class WebSocketController : ControllerBase
{
private readonly WebSocketManager _webSocketManager;
public WebSocketController(WebSocketManager webSocketManager)
{
_webSocketManager = webSocketManager;
}
[Route("/ws")]
public async Task Get(string name)
{
if (HttpContext.WebSockets.IsWebSocketRequest)
{
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
await _webSocketManager.AddWebSocketAsync(webSocket, name);
}
else
{
HttpContext.Response.StatusCode = StatusCodes.Status400BadRequest;
}
}
}
public class WebSocketManager
{
private ConcurrentDictionary<string, WebSocket> _sockets = new ConcurrentDictionary<string, WebSocket>();
private ConcurrentDictionary<string, string> _socketNames = new ConcurrentDictionary<string, string>();
public async Task AddWebSocketAsync(WebSocket webSocket, string name)
{
var socketId = Guid.NewGuid().ToString();
_sockets.TryAdd(socketId, webSocket);
_socketNames.TryAdd(socketId, name);
await HandleWebSocketAsync(socketId);
}
public async Task SendMessageAsync(string name, string message)
{
foreach(var socket in _socketNames)
{
var socketId = socket.Key;
if (socketId != null && socket.Value!=name && _sockets.TryGetValue(socketId, out var webSocket))
{
var buffer = Encoding.UTF8.GetBytes(message);
await webSocket.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
private async Task HandleWebSocketAsync(string socketId)
{
var webSocket = _sockets[socketId];
var buffer = new byte[1024 * 4];
WebSocketReceiveResult receiveResult;
do
{
receiveResult = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
string message = Encoding.UTF8.GetString(buffer, 0, receiveResult.Count);
if (!string.IsNullOrEmpty(message))
{
await SendMessageToOthersAsync(socketId, message);
}
}
while (!receiveResult.CloseStatus.HasValue);
await webSocket.CloseAsync(receiveResult.CloseStatus.Value, receiveResult.CloseStatusDescription, CancellationToken.None);
_sockets.TryRemove(socketId, out _);
_socketNames.TryRemove(socketId, out _);
}
private async Task SendMessageToOthersAsync(string senderSocketId, string message)
{
foreach (var socket in _sockets.Where(x => x.Key != senderSocketId))
{
if (socket.Value.State == WebSocketState.Open)
{
var buffer = Encoding.UTF8.GetBytes(message);
await socket.Value.SendAsync(new ArraySegment<byte>(buffer), WebSocketMessageType.Text, true, CancellationToken.None);
}
}
}
}