using System.Collections.Specialized; using System.Net.WebSockets; using System.Text; using XFEExtension.NetCore.Exceptions; namespace XFEExtension.NetCore.CyberComm; /// /// CyberComm服务器事件参数 /// /// 请求时的URL地址 /// 消息类型 /// 当前WebSocket /// 客户端请求头 /// 异常消息(如果有的话) /// 客户端IP地址 /// 文本消息 /// 二进制消息 /// 消息是否结束 public abstract record CyberCommServerEventArgs(Uri? RequestUrl, BackMessageType MessageType, WebSocket CurrentWebSocket, NameValueCollection WSHeader, XFECyberCommException? Exception, string IPAddress, string? TextMessage, byte[]? BinaryMessage, bool EndOfMessage) { private Func, WebSocketMessageType, CancellationToken, ValueTask>? SendHandler { get; init; } private Func>? CloseHandler { get; init; } /// 实际接受当前连接的本地监听端口,不受 Host 请求头或反向代理公开端口影响。 public int LocalPort { get; internal init; } /// /// 发送文本消息 /// /// 待发送的文本 /// /// 发送进程 public async Task ReplyMessage(string message) { try { var sendBuffer = Encoding.UTF8.GetBytes(message); if (SendHandler is not null) { var result = await SendHandler(sendBuffer, WebSocketMessageType.Text, CancellationToken.None).ConfigureAwait(false); if (!result.IsSuccess) throw result.Exception ?? new InvalidOperationException($"发送失败:{result.Status}"); } else await CurrentWebSocket.SendAsync(new ArraySegment(sendBuffer), WebSocketMessageType.Text, true, CancellationToken.None); } catch (Exception ex) { throw new XFECyberCommException("收到客户端数据后服务器端回复文本时出现异常", ex); } } /// /// 发送二进制消息 /// /// 二进制消息 /// /// public async Task ReplyBinaryMessage(byte[] bytes) { try { if (SendHandler is not null) { var result = await SendHandler(bytes, WebSocketMessageType.Binary, CancellationToken.None).ConfigureAwait(false); if (!result.IsSuccess) throw result.Exception ?? new InvalidOperationException($"发送失败:{result.Status}"); } else await CurrentWebSocket.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Binary, true, CancellationToken.None); } catch (Exception ex) { throw new XFECyberCommException("收到客户端数据后服务器端回复二进制数据时出现异常", ex); } } /// /// 关闭连接 /// /// public async Task Close() { try { if (CloseHandler is not null) await CloseHandler(WebSocketCloseStatus.NormalClosure, "Connection Closed", CancellationToken.None).ConfigureAwait(false); else await CurrentWebSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Connection Closed", CancellationToken.None); } catch (Exception ex) { throw new XFECyberCommException("关闭服务器端连接时出现异常", ex); } } /// /// 强制关闭连接 /// /// public void ForceClose() { try { CurrentWebSocket.Abort(); } catch (Exception ex) { throw new XFECyberCommException("强制关闭服务器端连接时出现异常", ex); } } internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, string message, string ipAddress, NameValueCollection wsHeader, bool endOfMessage, int localPort) : this(requestUrl, BackMessageType.Text, webSocket, wsHeader, null, ipAddress, message, null, endOfMessage) { LocalPort = localPort; } internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, byte[] bytes, string ipAddress, NameValueCollection wsHeader, bool endOfMessage, int localPort) : this(requestUrl, BackMessageType.Binary, webSocket, wsHeader, null, ipAddress, null, bytes, endOfMessage) { LocalPort = localPort; } internal CyberCommServerEventArgs(Uri? requestUrl, WebSocket webSocket, XFECyberCommException ex, string ipAddress, NameValueCollection wsHeader, int localPort) : this(requestUrl, BackMessageType.Error, webSocket, wsHeader, ex, ipAddress, null, null, true) { LocalPort = localPort; } internal CyberCommServerEventArgs WithTransport(CyberCommWebSocketPeer peer) => this with { SendHandler = peer.SendAsync, CloseHandler = peer.CloseAsync }; }