using System.Net.WebSockets; using System.Reflection; using System.Text; using System.Text.Json; using JNPF.Extras.WebSockets.Models; namespace JNPF.WebSockets; /// /// WebSocket 处理程序. /// public abstract class WebSocketHandler { /// /// WebSocket 连接管理. /// protected WebSocketConnectionManager WebSocketConnectionManager { get; set; } /// /// 初始化一个类型的新实例. /// public WebSocketHandler(WebSocketConnectionManager webSocketConnectionManager) { WebSocketConnectionManager = webSocketConnectionManager; } /// /// 连接. /// /// socket. /// public virtual async Task OnConnected(WebSocketClient socket) { WebSocketConnectionManager.AddSocket(socket); } /// /// 连接. /// /// 连接ID. /// socket. /// public virtual async Task OnConnected(string socketId, WebSocketClient socket) { WebSocketConnectionManager.AddSocket(socketId, socket); } /// /// 断开连接. /// /// /// public virtual async Task OnDisconnected(WebSocket socket) { string socketId = WebSocketConnectionManager.GetId(socket); if (!string.IsNullOrWhiteSpace(socketId)) await WebSocketConnectionManager.RemoveSocket(socketId).ConfigureAwait(false); } /// /// 发送消息给指定 id 的 socket. /// /// socket 客户端. /// 消息. /// public async Task SendMessageAsync(WebSocketClient client, string message) { if (client.WebSocket.State != WebSocketState.Open) return; byte[] encodedMessage = Encoding.UTF8.GetBytes(message); try { await client.WebSocket.SendAsync( buffer: new ArraySegment( array: encodedMessage, offset: 0, count: encodedMessage.Length), messageType: WebSocketMessageType.Text, endOfMessage: true, cancellationToken: CancellationToken.None).ConfigureAwait(false); } catch (WebSocketException e) { if (e.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) { await OnDisconnected(client.WebSocket); } } } /// /// 给指定 socket 发送信息. /// /// 连接ID. /// 消息内容. /// public async Task SendMessageAsync(string socketId, string message) { var socket = WebSocketConnectionManager.GetSocketById(socketId); if (socket != null) await SendMessageAsync(socket, message).ConfigureAwait(false); } /// /// 发送消息 全频道. /// /// 消息内容. /// public async Task SendMessageToAllAsync(string message) { foreach (var pair in WebSocketConnectionManager.GetAll()) { try { if (pair.Value.WebSocket.State == WebSocketState.Open) await SendMessageAsync(pair.Value, message).ConfigureAwait(false); } catch (WebSocketException e) { if (e.WebSocketErrorCode == WebSocketError.ConnectionClosedPrematurely) { await OnDisconnected(pair.Value.WebSocket); } } } } /// /// 给指定用户组发送信息. /// /// 用户ID. /// 消息内容. /// public async Task SendMessageToUserAsync(string userID, string message) { var sockets = WebSocketConnectionManager.GetAllFromUser(userID); if (sockets != null) { foreach (var socket in sockets) { await SendMessageAsync(socket, message); } } } /// /// 给指定租户组发送信息. /// /// 租户ID. /// 消息内容. /// public async Task SendMessageToTenantAsync(string tenantID, string message) { var sockets = WebSocketConnectionManager.GetAllFromTenant(tenantID); if (sockets != null) { foreach (var socket in sockets) { await SendMessageAsync(socket, message); } } } /// /// 给指定租户组发送信息. /// /// 租户ID. /// 消息内容. /// 除了某个用户. /// public async Task SendMessageToTenantAsync(string tenantID, string message, string except) { var sockets = WebSocketConnectionManager.GetAllFromTenant(tenantID); if (sockets != null) { foreach (var id in sockets) { if (id != except) await SendMessageAsync(id, message); } } } /// /// 获取租户组内全部用户ID. /// /// /// public List GetAllUserIdFromTenant(string tenantID) { List connectionList = new List(); foreach (var item in WebSocketConnectionManager.GetAllFromTenant(tenantID)) { var client = WebSocketConnectionManager.GetSocketById(item); if (client != null && !connectionList.Any(it => it.Equals(client.UserId))) connectionList.Add(client.UserId); } return connectionList; } /// /// 接收信息. /// /// /// /// /// public virtual async Task ReceiveAsync(WebSocketClient client, WebSocketReceiveResult result, string receivedMessage) { try { await SendMessageAsync(client, receivedMessage).ConfigureAwait(false); } catch (TargetParameterCountException) { await SendMessageAsync(client, JsonSerializer.Serialize(new { method = "error", msg = $"does not take parameters!" })).ConfigureAwait(false); } catch (ArgumentException) { await SendMessageAsync(client, JsonSerializer.Serialize(new { method = "error", msg = $"takes different arguments!" })).ConfigureAwait(false); } } }