diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer.Example/Cyaim.WebSocketServer.Example.csproj b/Cyaim.WebSocketServer/Cyaim.WebSocketServer.Example/Cyaim.WebSocketServer.Example.csproj index 9e15f10..d99e4ce 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer.Example/Cyaim.WebSocketServer.Example.csproj +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer.Example/Cyaim.WebSocketServer.Example.csproj @@ -12,9 +12,4 @@ - - - - - diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Cyaim.WebSocketServer.csproj b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Cyaim.WebSocketServer.csproj index 35d1f11..0c5365c 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Cyaim.WebSocketServer.csproj +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Cyaim.WebSocketServer.csproj @@ -25,10 +25,6 @@ README.md - - E:\WorkSpaces\WebSocketServer\Cyaim.WebSocketServer\Cyaim.WebSocketServer\Cyaim.WebSocketServer.xml - - @@ -42,10 +38,6 @@ - - - - diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Attributes/WebSocketAttribute.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Attributes/WebSocketAttribute.cs index e7099ab..ebb246c 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Attributes/WebSocketAttribute.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Attributes/WebSocketAttribute.cs @@ -1,21 +1,17 @@ using System; -using System.Collections.Generic; -using System.Text; namespace Cyaim.WebSocketServer.Infrastructure.Attributes { /// /// WebSocket Endpoint mark /// - [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + [AttributeUsage(AttributeTargets.Method)] public class WebSocketAttribute : Attribute { /// /// Mark action use action name /// - public WebSocketAttribute() - { - } + public WebSocketAttribute() { } /// /// Mark action use method value @@ -31,4 +27,4 @@ public WebSocketAttribute(string method) : this() /// public string Method { get; set; } } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Cluster/GlobalClusterCenter.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Cluster/GlobalClusterCenter.cs index a107af2..14575fc 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Cluster/GlobalClusterCenter.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Cluster/GlobalClusterCenter.cs @@ -1,8 +1,6 @@ using Cyaim.WebSocketServer.Infrastructure.Configures; -using System; using System.Collections.Generic; using System.Net.WebSockets; -using System.Text; namespace Cyaim.WebSocketServer.Infrastructure.Cluster { @@ -17,8 +15,8 @@ public static class GlobalClusterCenter public static ClusterOption ClusterContext { get; set; } /// - /// All nodes + /// All nodes /// public static List Nodes { get; set; } } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ClusterOption.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ClusterOption.cs index c428b4f..6ae0039 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ClusterOption.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ClusterOption.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace Cyaim.WebSocketServer.Infrastructure.Configures +namespace Cyaim.WebSocketServer.Infrastructure.Configures { /// /// Cluster configure @@ -30,10 +26,8 @@ public class ClusterOption /// Only NodeLevel are valid for Master. /// public bool IsEnableLoadBalance { get; set; } - } - /// /// Service node /// @@ -43,9 +37,10 @@ public enum ServiceLevel /// Master node /// Master, + /// /// Slave node /// - Slave, + Slave } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ConstructorParameter.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ConstructorParameter.cs index fd2bf86..12c799a 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ConstructorParameter.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/ConstructorParameter.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using System.Text; +using System.Reflection; namespace Cyaim.WebSocketServer.Infrastructure.Configures { @@ -20,4 +17,4 @@ public struct ConstructorParameter /// public ParameterInfo[] ParameterInfos { get; set; } } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WatchAssemblyContext.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WatchAssemblyContext.cs index bd09e15..88f6bac 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WatchAssemblyContext.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WatchAssemblyContext.cs @@ -1,9 +1,7 @@ using System; using System.Collections.Concurrent; using System.Collections.Generic; -using System.Dynamic; using System.Reflection; -using System.Text; namespace Cyaim.WebSocketServer.Infrastructure.Configures { @@ -18,7 +16,7 @@ public class WatchAssemblyContext public string WatchAssemblyPath { get; set; } /// - /// Type in assemblys + /// Type in assemblies /// public List WatchAssemblyTypes { get; set; } @@ -41,13 +39,13 @@ public class WatchAssemblyContext /// Constructor parameter list /// K class type,V class constructor parameter list /// - public Dictionary CoustructorParameters { get; set; } + public Dictionary ConstructorParameters { get; set; } /// /// Constructor most parameter in class /// K Class type,V Constructor parameter /// - public Dictionary MaxCoustructorParameters { get; set; } + public Dictionary MaxConstructorParameters { get; set; } /// /// Method parameter list in class public method @@ -55,4 +53,4 @@ public class WatchAssemblyContext /// public Dictionary MethodParameters { get; set; } } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketEndPoint.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketEndPoint.cs index 7e23cd6..3e90224 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketEndPoint.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketEndPoint.cs @@ -1,7 +1,5 @@ using System; -using System.Collections.Generic; using System.Reflection; -using System.Text; namespace Cyaim.WebSocketServer.Infrastructure.Configures { @@ -39,6 +37,5 @@ public class WebSocketEndPoint /// Endpoint where class /// public Type Class { get; set; } - } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketRouteOption.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketRouteOption.cs index afec877..241db9a 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketRouteOption.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Configures/WebSocketRouteOption.cs @@ -4,12 +4,11 @@ using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; -using System.IO; -using System.Reflection; -using System.Text; using System.Text.Json; using System.Threading.Tasks; +// ReSharper disable ClassWithVirtualMembersNeverInherited.Global + namespace Cyaim.WebSocketServer.Infrastructure.Configures { /// @@ -85,7 +84,6 @@ public class WebSocketRouteOption /// logger /// WebSocket configure option /// - public delegate Task WebSocketChannelHandler(HttpContext context, ILogger logger, WebSocketRouteOption webSocketOptions); /// @@ -120,61 +118,62 @@ public virtual Task OnBeforeConnection(HttpContext context, WebSocketRoute return Task.FromResult(true); } - /// - /// Close connectioned handler + /// Close Connected handler /// /// /// /// /// /// - public delegate Task DisConnectionedHandler(HttpContext context, WebSocketRouteOption webSocketOptions, string channel, ILogger logger); + public delegate Task DisConnectedHandler(HttpContext context, WebSocketRouteOption webSocketOptions, string channel, ILogger logger); /// - /// Close connectioned call + /// Close Connected call /// - public event DisConnectionedHandler DisConnectionedEvent; + public event DisConnectedHandler DisConnectedEvent; /// - /// DisConnectionedEvent entry + /// DisConnectedEvent entry /// /// /// /// /// /// - public virtual Task OnDisConnectioned(HttpContext context, WebSocketRouteOption webSocketOptions, string channel, ILogger logger) + public virtual Task OnDisConnected(HttpContext context, WebSocketRouteOption webSocketOptions, string channel, ILogger logger) { - if (DisConnectionedEvent != null) + if (DisConnectedEvent != null) { - return DisConnectionedEvent(context, webSocketOptions, channel, logger); + return DisConnectedEvent(context, webSocketOptions, channel, logger); } return Task.CompletedTask; } - #endregion + #endregion #region System.Text.Json Options + /// - /// JsonSerialiazerOptions + /// JsonSerializerOptions /// - public JsonSerializerOptions DefaultRequestJsonSerialiazerOptions { get; set; } = new JsonSerializerOptions + public JsonSerializerOptions DefaultRequestJsonSerializerOptions { get; set; } = new JsonSerializerOptions { // 设置为 true 以忽略属性名称的大小写 PropertyNameCaseInsensitive = true, - WriteIndented = false, + WriteIndented = false }; /// - /// JsonSerialiazerOptions + /// JsonSerializerOptions /// - public JsonSerializerOptions DefaultResponseJsonSerialiazerOptions { get; set; } = new JsonSerializerOptions + public JsonSerializerOptions DefaultResponseJsonSerializerOptions { get; set; } = new JsonSerializerOptions { // 设置为 true 以忽略属性名称的大小写 PropertyNameCaseInsensitive = true, - WriteIndented = false, + WriteIndented = false }; + #endregion } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/DataTypes.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/DataTypes.cs index cb23bea..fd24d75 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/DataTypes.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/DataTypes.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Text; using System.Text.Json; using System.Text.Json.Nodes; @@ -12,90 +9,35 @@ namespace Cyaim.WebSocketServer.Infrastructure.Handlers /// public static class DataTypes { - #region BaseType - /// - /// System.SByte - /// - public const string Type_SByte = "System.SByte"; - /// - /// System.Byte - /// - public const string Type_Byte = "System.Byte"; - /// - /// System.Int16 - /// - public const string Type_Short = "System.Int16"; - /// - /// System.UInt16 - /// - public const string Type_UShort = "System.UInt16"; - /// - /// System.Int32 - /// - public const string Type_Int = "System.Int32"; - /// - /// System.UInt32 - /// - public const string Type_UInt = "System.UInt32"; - /// - /// System.Int64 - /// - public const string Type_Long = "System.Int64"; - /// - /// System.UInt64 - /// - public const string Type_ULong = "System.UInt64"; - /// - /// System.Single - /// - public const string Type_Float = "System.Single"; - /// - /// System.Double - /// - public const string Type_Double = "System.Double"; - /// - /// System.Boolean - /// - public const string Type_Bool = "System.Boolean"; - /// - /// System.Char - /// - public const string Type_Char = "System.Char"; - /// - /// System.Decimal - /// - public const string Type_Decimal = "System.Decimal"; - /// - /// System.String - /// - public const string Type_String = "System.String"; - #endregion - /// /// System.DateTime /// - public const string Type_DateTime = "System.DateTime"; + private const string Type_DateTime = "System.DateTime"; + /// /// System.DateTimeOffset /// - public const string Type_DateTimeOffset = "System.DateTimeOffset"; + private const string Type_DateTimeOffset = "System.DateTimeOffset"; /// /// System.Text.Json.JsonNode /// - public const string Type_JsonNode = "System.Text.Json.JsonNode"; + private const string Type_JsonNode = "System.Text.Json.JsonNode"; + /// /// System.Text.Json.JsonObject /// - public const string Type_JsonObject = "System.Text.Json.JsonObject"; + private const string Type_JsonObject = "System.Text.Json.JsonObject"; + /// /// System.Text.Json.JsonArray /// - public const string Type_JsonArray = "System.Text.Json.JsonArray"; + private const string Type_JsonArray = "System.Text.Json.JsonArray"; + /// /// System.Text.Json.JsonValue /// - public const string Type_JsonValue = "System.Text.Json.JsonValue"; + private const string Type_JsonValue = "System.Text.Json.JsonValue"; /// /// JsonNode value to target type @@ -105,36 +47,28 @@ public static class DataTypes /// public static object ConvertTo(this Type type, JsonNode value) { - try + return type.FullName switch { - return type.FullName switch - { - Type_String => value.GetValue(), - Type_SByte => value.GetValue(), - Type_Byte => value.GetValue(), - Type_Short => value.GetValue(), - Type_UShort => value.GetValue(), - Type_Int => value.GetValue(), - Type_UInt => value.GetValue(), - Type_Long => value.GetValue(), - Type_ULong => value.GetValue(), - Type_Float => value.GetValue(), - Type_Double => value.GetValue(), - Type_Bool => value.GetValue(), - Type_DateTime => value.GetValue(), - Type_DateTimeOffset => value.GetValue(), - Type_Char => value.GetValue(), - Type_Decimal => value.GetValue(), - _ => JsonSerializer.Deserialize(value, type), - }; - } - catch (Exception) - { - throw; - } + Type_String => value.GetValue(), + Type_SByte => value.GetValue(), + Type_Byte => value.GetValue(), + Type_Short => value.GetValue(), + Type_UShort => value.GetValue(), + Type_Int => value.GetValue(), + Type_UInt => value.GetValue(), + Type_Long => value.GetValue(), + Type_ULong => value.GetValue(), + Type_Float => value.GetValue(), + Type_Double => value.GetValue(), + Type_Bool => value.GetValue(), + Type_DateTime => value.GetValue(), + Type_DateTimeOffset => value.GetValue(), + Type_Char => value.GetValue(), + Type_Decimal => value.GetValue(), + _ => value.Deserialize(type) + }; } - /// /// object to real type /// @@ -143,56 +77,47 @@ public static object ConvertTo(this Type type, JsonNode value) /// public static object ConvertTo(this Type type, object value) { - try + switch (type.FullName) { - switch (type.FullName) - { - case Type_String: - return Convert.ToString(value); - case Type_SByte: - return Convert.ToSByte(value); - case Type_Byte: - return Convert.ToByte(value); - case Type_Short: - return Convert.ToInt16(value); - case Type_UShort: - return Convert.ToUInt16(value); - case Type_Int: - return Convert.ToInt32(value); - case Type_UInt: - return Convert.ToUInt32(value); - case Type_Long: - return Convert.ToInt64(value); - case Type_ULong: - return Convert.ToUInt64(value); - case Type_Float: - return Convert.ToSingle(value); - case Type_Double: - return Convert.ToDouble(value); - case Type_Bool: - return Convert.ToBoolean(value); - case Type_Char: - return Convert.ToChar(value); - case Type_Decimal: - return Convert.ToChar(value); - case Type_DateTime: - return Convert.ToDateTime(value); - case Type_DateTimeOffset: - return DateTimeOffset.Parse(value.ToString()); - - case Type_JsonNode: - case Type_JsonObject: - case Type_JsonArray: - case Type_JsonValue: - return JsonNode.Parse(value.ToString()); - default: - return null; - } - } - catch (Exception) - { - - throw; + case Type_String: + return Convert.ToString(value); + case Type_SByte: + return Convert.ToSByte(value); + case Type_Byte: + return Convert.ToByte(value); + case Type_Short: + return Convert.ToInt16(value); + case Type_UShort: + return Convert.ToUInt16(value); + case Type_Int: + return Convert.ToInt32(value); + case Type_UInt: + return Convert.ToUInt32(value); + case Type_Long: + return Convert.ToInt64(value); + case Type_ULong: + return Convert.ToUInt64(value); + case Type_Float: + return Convert.ToSingle(value); + case Type_Double: + return Convert.ToDouble(value); + case Type_Bool: + return Convert.ToBoolean(value); + case Type_Char: + return Convert.ToChar(value); + case Type_Decimal: + return Convert.ToChar(value); + case Type_DateTime: + return Convert.ToDateTime(value); + case Type_DateTimeOffset: + return DateTimeOffset.Parse(value.ToString()); + case Type_JsonNode: + case Type_JsonObject: + case Type_JsonArray: + case Type_JsonValue: + return JsonNode.Parse(value.ToString()); + default: + return null; } } @@ -203,36 +128,102 @@ public static object ConvertTo(this Type type, object value) /// public static bool IsBasicType(this Type type) { - try + switch (type.FullName) { - switch (type.FullName) - { - case Type_String: - case Type_SByte: - case Type_Byte: - case Type_Short: - case Type_UShort: - case Type_Int: - case Type_UInt: - case Type_Long: - case Type_ULong: - case Type_Float: - case Type_Double: - case Type_Bool: - //case Type_DateTime: - //case Type_DateTimeOffset: - case Type_Char: - case Type_Decimal: - return true; - default: - return false; - } - } - catch (Exception) - { - - throw; + case Type_String: + case Type_SByte: + case Type_Byte: + case Type_Short: + case Type_UShort: + case Type_Int: + case Type_UInt: + case Type_Long: + case Type_ULong: + case Type_Float: + case Type_Double: + case Type_Bool: + //case Type_DateTime: + //case Type_DateTimeOffset: + case Type_Char: + case Type_Decimal: + return true; + default: + return false; } } + + #region BaseType + + /// + /// System.SByte + /// + private const string Type_SByte = "System.SByte"; + + /// + /// System.Byte + /// + private const string Type_Byte = "System.Byte"; + + /// + /// System.Int16 + /// + private const string Type_Short = "System.Int16"; + + /// + /// System.UInt16 + /// + private const string Type_UShort = "System.UInt16"; + + /// + /// System.Int32 + /// + private const string Type_Int = "System.Int32"; + + /// + /// System.UInt32 + /// + private const string Type_UInt = "System.UInt32"; + + /// + /// System.Int64 + /// + private const string Type_Long = "System.Int64"; + + /// + /// System.UInt64 + /// + private const string Type_ULong = "System.UInt64"; + + /// + /// System.Single + /// + private const string Type_Float = "System.Single"; + + /// + /// System.Double + /// + private const string Type_Double = "System.Double"; + + /// + /// System.Boolean + /// + private const string Type_Bool = "System.Boolean"; + + /// + /// System.Char + /// + private const string Type_Char = "System.Char"; + + /// + /// System.Decimal + /// + private const string Type_Decimal = "System.Decimal"; + + /// + /// System.String + /// + private const string Type_String = "System.String"; + + #endregion } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/IWebSocketHandler.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/IWebSocketHandler.cs index 4fef7de..42bd8d1 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/IWebSocketHandler.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/IWebSocketHandler.cs @@ -2,9 +2,6 @@ using Cyaim.WebSocketServer.Middlewares; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; -using System; -using System.Collections.Generic; -using System.Text; using System.Threading.Tasks; namespace Cyaim.WebSocketServer.Infrastructure.Handlers @@ -37,7 +34,6 @@ public interface IWebSocketHandler /// /// Task ConnectionEntry(HttpContext context, ILogger logger, WebSocketRouteOption webSocketOptions); - } /// @@ -46,7 +42,7 @@ public interface IWebSocketHandler public class WebSocketHandlerMetadata { /// - /// Describe the function of the handle and how to use it + /// Describe the function of the handle and how to use it /// public string Describe { get; set; } @@ -60,4 +56,4 @@ public class WebSocketHandlerMetadata /// public bool CanHandleText { get; set; } } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcChannelHandler.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcChannelHandler.cs index 7f8cca1..1c060d1 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcChannelHandler.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcChannelHandler.cs @@ -10,8 +10,6 @@ using System.IO; using System.Linq; using System.Net.WebSockets; -using System.Reflection; -using System.Runtime.InteropServices.ComTypes; using System.Text; using System.Text.Json; using System.Text.Json.Nodes; @@ -25,12 +23,6 @@ namespace Cyaim.WebSocketServer.Infrastructure.Handlers.MvcHandler /// public class MvcChannelHandler : IWebSocketHandler { - /// - /// Connected clients by mvc channel - /// - public static ConcurrentDictionary Clients { get; set; } = new ConcurrentDictionary(); - - private ILogger logger; private WebSocketRouteOption webSocketOption; @@ -43,15 +35,19 @@ public MvcChannelHandler(int receiveBufferSize = 4 * 1024) ReceiveTextBufferSize = ReceiveBinaryBufferSize = receiveBufferSize; } + /// + /// Connected clients by mvc channel + /// + public static ConcurrentDictionary Clients { get; set; } = new ConcurrentDictionary(); /// /// Metadata used when parsing the handler /// - public WebSocketHandlerMetadata Metadata { get; } = new WebSocketHandlerMetadata() + public WebSocketHandlerMetadata Metadata { get; } = new WebSocketHandlerMetadata { Describe = "Provide MVC forwarding handler", CanHandleBinary = true, - CanHandleText = true, + CanHandleText = true }; /// @@ -82,23 +78,24 @@ public async Task ConnectionEntry(HttpContext context, ILogger - ///// Forward by WebSocket transfer type - ///// - ///// - ///// - ///// - //private async Task MvcForward(HttpContext context, WebSocket webSocket) - //{ - // var buffer = new byte[ReceiveTextBufferSize]; - // ArraySegment bufferSeg = new ArraySegment(buffer); - - // try - // { - // WebSocketReceiveResult result = await webSocket.ReceiveAsync(bufferSeg, CancellationToken.None); - // //switch (result.MessageType) - // //{ - // // case WebSocketMessageType.Binary: - // // await MvcBinaryForward(context, webSocket, result, buffer); - // // break; - // // case WebSocketMessageType.Text: - // // await MvcTextForward(webSocket, context, result, buffer); - // // break; - // //} - // await MvcForward(webSocket, context, result, bufferSeg); - - // //链接断开 - // await webSocket.CloseAsync(webSocket.CloseStatus == null ? - // webSocket.State == WebSocketState.Aborted ? - // WebSocketCloseStatus.InternalServerError : WebSocketCloseStatus.NormalClosure - // : webSocket.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); - // } - // catch (OperationCanceledException ex) - // { - // logger.LogInformation($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> 终止接收数据({context.Connection.Id})\r\nStatus:{(webSocket.CloseStatus.HasValue ? webSocket.CloseStatus.ToString() : "ServerClose")}\r\n{ex.Message}"); - // } - //} - - ///// - ///// Handle request content - ///// - ///// - ///// - ///// - ///// - ///// - //private async Task MvcForward(WebSocket webSocket, HttpContext context, WebSocketReceiveResult result, ArraySegment buffer) - //{ - - // long requestTime = DateTime.Now.Ticks; - // StringBuilder json = new StringBuilder(); - - // //处理第一次返回的数据 - // json = json.Append(Encoding.UTF8.GetString(buffer[..result.Count])); - - // //第一次接受已经接受完数据了 - // if (result.EndOfMessage) - // { - // try - // { - // await MvcForwardSendData(webSocket, context, result, json, requestTime); - // } - // catch (Exception ex) - // { - // logger.LogError(ex, ex.Message); - // } - // finally - // { - // json = json.Clear(); - // } - // } - - // //等待客户端发送数据,第二次接受数据 - // while (!result.CloseStatus.HasValue) - // { - // try - // { - // if (!(webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent)) - // { - // break; - // } - - // result = await webSocket.ReceiveAsync(buffer, CancellationToken.None); - // requestTime = DateTime.Now.Ticks; - - // json = json.Append(Encoding.UTF8.GetString(buffer[..result.Count])); - - // if (!result.EndOfMessage || result.CloseStatus.HasValue) - // { - // continue; - // } - - // await MvcForwardSendData(webSocket, context, result, json, requestTime); - - // json = json.Clear(); - // } - // catch (OperationCanceledException ex) - // { - // logger.LogInformation($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> 终止接收数据({context.Connection.Id})\r\nStatus:{(webSocket.CloseStatus.HasValue ? webSocket.CloseStatus.ToString() : "ServerClose")}\r\n{ex.Message}"); - // } - // catch (Exception ex) - // { - // logger.LogError(ex, ex.Message); - // } - - // } - - - //} - #endregion - /// /// Forward by WebSocket transfer type /// @@ -258,12 +141,12 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) { try { - CancellationTokenSource connCts = new CancellationTokenSource(); - string wsCloseDesc = string.Empty; - using MemoryStream wsReceiveReader = new MemoryStream(ReceiveTextBufferSize); + var connCts = new CancellationTokenSource(); + string wsCloseDesc; + using var wsReceiveReader = new MemoryStream(ReceiveTextBufferSize); do { - long requestTime = DateTime.Now.Ticks; + var requestTime = DateTime.Now.Ticks; WebSocketReceiveResult result = null; try { @@ -274,16 +157,13 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) connCts.Cancel(); goto CONTINUE; } - else - { - await Task.Delay(1000).ConfigureAwait(false); - goto CONTINUE; - } - + await Task.Delay(1000, connCts.Token).ConfigureAwait(false); + goto CONTINUE; } #region 接收数据 - byte[] buffer = ArrayPool.Shared.Rent(ReceiveTextBufferSize); + + var buffer = ArrayPool.Shared.Rent(ReceiveTextBufferSize); while ((result = await webSocket.ReceiveAsync(new ArraySegment(buffer), CancellationToken.None)).Count > 0) { try @@ -297,6 +177,7 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) } //await wsReceiveReader.WriteAsync(buffer, 0, result.Count); + // ReSharper disable once MethodSupportsCancellation await wsReceiveReader.WriteAsync(buffer.AsMemory(0, result.Count)); // 已经接受完数据了 if (result.EndOfMessage || result.CloseStatus.HasValue) @@ -313,6 +194,7 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) ArrayPool.Shared.Return(buffer); } } + #endregion if (result == null) @@ -331,22 +213,20 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) //JsonDocument document = JsonDocument.Parse(wsReceiveReader.GetBuffer()); MvcRequestScheme requestScheme; JsonObject requestBody; - using (JsonDocument doc = JsonDocument.Parse(wsReceiveReader.GetBuffer())) + using (var doc = JsonDocument.Parse(wsReceiveReader.GetBuffer())) { - JsonElement root = doc.RootElement; - bool hasBody = root.TryGetProperty("Body", out JsonElement body); + var root = doc.RootElement; + var hasBody = root.TryGetProperty("Body", out var body); if (!hasBody) { hasBody = root.TryGetProperty("body", out body); } - - requestScheme = doc.Deserialize(webSocketOption.DefaultRequestJsonSerialiazerOptions); - requestBody = body.ValueKind == JsonValueKind.Undefined ? null : (JsonNode.Parse(body.GetRawText())?.AsObject()); + requestScheme = doc.Deserialize(webSocketOption.DefaultRequestJsonSerializerOptions); + requestBody = body.ValueKind == JsonValueKind.Undefined ? null : JsonNode.Parse(body.GetRawText())?.AsObject(); } //requestScheme = JsonSerializer.Deserialize(wsReceiveReader.GetBuffer(), webSocketOption.DefaultRequestJsonSerialiazerOptions); await MvcForwardSendData(webSocket, context, result, requestScheme, requestBody, requestTime); - CONTINUE:; } catch (Exception ex) @@ -356,16 +236,13 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) finally { wsCloseDesc = result?.CloseStatusDescription; - - wsReceiveReader.Flush(); + await wsReceiveReader.FlushAsync(connCts.Token); wsReceiveReader.SetLength(0); wsReceiveReader.Seek(0, SeekOrigin.Begin); wsReceiveReader.Position = 0; } - } while (!connCts.IsCancellationRequested); - //switch (result.MessageType) //{ // case WebSocketMessageType.Binary: @@ -379,10 +256,7 @@ private async Task MvcForward(HttpContext context, WebSocket webSocket) // 连接断开 if (webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent) { - await webSocket.CloseAsync(webSocket.CloseStatus == null ? - webSocket.State == WebSocketState.Aborted ? - WebSocketCloseStatus.InternalServerError : WebSocketCloseStatus.NormalClosure - : webSocket.CloseStatus.Value, wsCloseDesc, CancellationToken.None); + await webSocket.CloseAsync(webSocket.CloseStatus ?? (webSocket.State == WebSocketState.Aborted ? WebSocketCloseStatus.InternalServerError : WebSocketCloseStatus.NormalClosure), wsCloseDesc, CancellationToken.None); } } catch (Exception ex) @@ -414,7 +288,7 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, object invokeResult = await MvcDistributeAsync(webSocketOption, context, webSocket, request, requestBody, logger); // 发送结果给客户端 - string serialJson = JsonSerializer.Serialize(invokeResult, webSocketOption.DefaultResponseJsonSerialiazerOptions); + var serialJson = JsonSerializer.Serialize(invokeResult, webSocketOption.DefaultResponseJsonSerializerOptions); await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(serialJson)), result.MessageType, result.EndOfMessage, CancellationToken.None); } catch (JsonException ex) @@ -423,17 +297,10 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, { Status = 1, RequestTime = requsetTicks, - ComplateTime = DateTime.Now.Ticks, + CompleteTime = DateTime.Now.Ticks }; logger.LogTrace(mvcRespEx, mvcRespEx.Message); } - catch (Exception) - { - - throw; - } - - } /// @@ -456,8 +323,8 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, //按节点请求转发 JsonObject requestBody = null; - string jsonString = JsonSerializer.Serialize(request.Body, webSocketOption.DefaultRequestJsonSerialiazerOptions); - JsonNode requestJsonNode = JsonNode.Parse(jsonString); + var jsonString = JsonSerializer.Serialize(request.Body, webSocketOption.DefaultRequestJsonSerializerOptions); + var requestJsonNode = JsonNode.Parse(jsonString); if (requestJsonNode != null) { requestBody = requestJsonNode.AsObject(); @@ -465,7 +332,7 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, object invokeResult = await MvcDistributeAsync(webSocketOption, context, webSocket, request, requestBody, logger); // 发送结果给客户端 - string serialJson = JsonSerializer.Serialize(invokeResult, webSocketOption.DefaultResponseJsonSerialiazerOptions); + var serialJson = JsonSerializer.Serialize(invokeResult, webSocketOption.DefaultResponseJsonSerializerOptions); await webSocket.SendAsync(new ArraySegment(Encoding.UTF8.GetBytes(serialJson)), result.MessageType, result.EndOfMessage, CancellationToken.None); } catch (JsonException ex) @@ -474,17 +341,10 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, { Status = 1, RequestTime = requsetTicks, - ComplateTime = DateTime.Now.Ticks, + CompleteTime = DateTime.Now.Ticks }; logger.LogTrace(mvcRespEx, mvcRespEx.Message); } - catch (Exception) - { - - throw; - } - - } /// @@ -504,14 +364,12 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, { return; } - - MvcRequestScheme request = JsonSerializer.Deserialize(json.ToString(), webSocketOption.DefaultRequestJsonSerialiazerOptions); + var request = JsonSerializer.Deserialize(json.ToString(), webSocketOption.DefaultRequestJsonSerializerOptions); if (request == null) { logger.LogTrace(string.Format(I18nText.WS_INTERACTIVE_TEXT_TEMPALTE, context.Connection.RemoteIpAddress, context.Connection.RemotePort, context.Connection.Id, I18nText.MvcForwardSendData_RequestBodyFormatError + json)); return; } - await MvcForwardSendData(webSocket, context, result, request, requsetTicks).ConfigureAwait(false); } catch (JsonException ex) @@ -520,19 +378,378 @@ private async Task MvcForwardSendData(WebSocket webSocket, HttpContext context, { Status = 1, RequestTime = requsetTicks, - ComplateTime = DateTime.Now.Ticks, + CompleteTime = DateTime.Now.Ticks }; logger.LogTrace(mvcRespEx, mvcRespEx.Message); } - catch (Exception) + } + + /// + /// Forward request to endpoint method + /// + /// + /// + /// + /// + /// + /// + /// + public static async Task MvcDistributeAsync(WebSocketRouteOption webSocketOptions, HttpContext context, WebSocket webSocket, MvcRequestScheme request, JsonObject requestBody, ILogger logger) + { + var requestTime = DateTime.Now.Ticks; + var requestPath = request.Target.ToLower(); + try { + // 从键值对中获取对应的执行函数 + webSocketOptions.WatchAssemblyContext.WatchMethods.TryGetValue(requestPath, out var method); + if (method == null) + { + goto NotFound; + } + var @class = webSocketOptions.WatchAssemblyContext.WatchEndPoint.FirstOrDefault(x => x.MethodPath == requestPath)?.Class; + if (@class == null) + { + //找不到访问目标 + goto NotFound; + } + + #region 注入Socket的HttpContext和WebSocket客户端 + + var contextInfo = @class.GetProperty(webSocketOptions.InjectionHttpContextPropertyName); + var socketInfo = @class.GetProperty(webSocketOptions.InjectionWebSocketClientPropertyName); + webSocketOptions.WatchAssemblyContext.MaxConstructorParameters.TryGetValue(@class, out var constructorParameter); + var instanceParams = new object[constructorParameter.ParameterInfos.Length]; + // 从Scope从DI容器提取目标类构造函数所需的对象 + var serviceScopeFactory = WebSocketRouteOption.ApplicationServices.GetService(); + var serviceScope = serviceScopeFactory.CreateScope(); + var scopeIocProvider = serviceScope.ServiceProvider; + for (var i = 0; i < constructorParameter.ParameterInfos.Length; i++) + { + var item = constructorParameter.ParameterInfos[i]; + if (webSocketOptions.ApplicationServiceCollection == null) + { + logger.LogWarning("Cannot inject target constructor parameter because DI container WebSocketRouteOption.ApplicationServiceCollection is null."); + break; + } + var nonSingleton = webSocketOptions.ApplicationServiceCollection.FirstOrDefault(x => x.ServiceType == item.ParameterType); + instanceParams[i] = nonSingleton == null || nonSingleton.Lifetime == ServiceLifetime.Singleton + ? WebSocketRouteOption.ApplicationServices.GetService(item.ParameterType) + : scopeIocProvider.GetService(item.ParameterType); + } + var inst = Activator.CreateInstance(@class, instanceParams); + + // 注入目标类中的帮助属性HttpContext、WebSocket + if (contextInfo != null && contextInfo.CanWrite) + { + contextInfo.SetValue(inst, context); + } + if (socketInfo != null && socketInfo.CanWrite) + { + socketInfo.SetValue(inst, webSocket); + } + + #endregion - throw; + var mvcResponse = new MvcResponseScheme { Status = 0, RequestTime = requestTime }; + + #region 注入调用方法参数 + + webSocketOptions.WatchAssemblyContext.MethodParameters.TryGetValue(method, out var methodParam); + object invokeResult; + if (requestBody == null || requestBody.Count <= 0) + { + var args = Array.Empty(); + // 有参方法 + if (methodParam != null && methodParam.Length > 0) + { + args = new object[methodParam.LongLength]; + + // 为每个参数设置其类型的默认值 + for (var i = 0; i < methodParam.Length; i++) + { + var item = methodParam[i]; + if (item.HasDefaultValue) + { + args[i] = item.DefaultValue; + continue; + } + // 如果参数类型是值类型,则使用类型的零值 + if (item.ParameterType.IsValueType) + { + args[i] = Activator.CreateInstance(item.ParameterType); + } + else + { + // 如果参数类型是引用类型,则使用 null + args[i] = null; + } + } + } + else if (methodParam.Length < 0) + { + throw new InvalidOperationException("请求的目标终结点参数异常"); + } + invokeResult = method.Invoke(inst, args); + } + else + { + // 异步调用目标方法 + var invoke = new Task(() => + { + var methodParm = new object[methodParam.Length]; + for (var i = 0; i < methodParam.Length; i++) + { + var item = methodParam[i]; + + // 检测方法中的参数是否是C#定义的基本类型 + object parmVal = null; + try + { + // 按参数名提取JsonNode + var hasVal = requestBody.TryGetPropertyValue(item.Name, out var JProp); + if (hasVal) + { + parmVal = item.ParameterType.ConvertTo(requestBody[item.Name]); + } + else + { + continue; + } + } + catch (JsonException ex) + { + // 反序列化失败 + logger.LogTrace($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> {requestPath} An exception occurred while operating the request data JSON\r\n{ex.Message}\r\n{ex.StackTrace}"); + } + catch (FormatException ex) + { + // ConvertTo 抛出 类型转换失败 + logger.LogTrace($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> {requestPath} Parameter data formatting exception in the request body\r\n{ex.Message}\r\n{ex.StackTrace}"); + } + methodParm[i] = parmVal; + } + return method.Invoke(inst, methodParm); + }); + invoke.Start(); + invokeResult = await invoke; + } + + // Async api support + if (invokeResult is Task) + { + dynamic invokeResultTask = invokeResult; + await invokeResultTask; + invokeResult = invokeResultTask.Result; + } + + #endregion + + // Dispose ioc scope + serviceScope?.Dispose(); + mvcResponse.Id = request.Id; + mvcResponse.Target = request.Target; + mvcResponse.Body = invokeResult; + mvcResponse.CompleteTime = DateTime.Now.Ticks; + return mvcResponse; } + catch (Exception ex) + { + var resp = new MvcResponseScheme { Id = request.Id, Status = 1, RequestTime = requestTime, CompleteTime = DateTime.Now.Ticks }; + if (webSocketOptions.IsDevelopment) + { + resp.Msg = $@"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> Target:{requestPath}\r\n{ex.Message}\r\n{ex.StackTrace}"; + } + return resp; + } + NotFound: + return new MvcResponseScheme { Id = request.Id, Status = 2, Msg = $@"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> Target:{requestPath} not found", RequestTime = requestTime, CompleteTime = DateTime.Now.Ticks }; + } + + /// + /// Client close connection + /// + /// + /// + /// + /// + private async Task MvcChannel_OnDisconnected(HttpContext context, WebSocket webSocket, WebSocketRouteOption webSocketOptions, ILogger logger) + { + var msg = string.Empty; + if (webSocket?.CloseStatus.HasValue ?? false) + { + msg = webSocket.CloseStatus.Value switch + { + WebSocketCloseStatus.Empty => "No error specified.", + WebSocketCloseStatus.EndpointUnavailable => "Indicates an endpoint is being removed. Either the server or client will become unavailable.", + WebSocketCloseStatus.InternalServerError => "The connection will be closed by the server because of an error on the server.", + WebSocketCloseStatus.InvalidMessageType => "The client or server is terminating the connection because it cannot accept the data type it received.", + WebSocketCloseStatus.InvalidPayloadData => "The client or server is terminating the connection because it has received data inconsistent with the message type.", + WebSocketCloseStatus.MandatoryExtension => "The client is terminating the connection because it expected the server to negotiate an extension.", + WebSocketCloseStatus.MessageTooBig => "Reserved for future use.", + WebSocketCloseStatus.NormalClosure => "The connection has closed after the request was fulfilled.", + WebSocketCloseStatus.PolicyViolation => "The connection will be closed because an endpoint has received a message that violates its policy.", + WebSocketCloseStatus.ProtocolError => "The client or server is terminating the connection because of a protocol error.", + _ => msg + }; + } + else + { + msg = "The connection of this client is shutting down."; + } + logger.LogInformation($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> Disconnected({context.Connection.Id})\r\nStatus:{webSocket?.CloseStatus.ToString() ?? "NoHandshakeSucceeded"}\r\n{msg}"); + try + { + await MvcChannel_OnDisConnected(context, webSocketOptions, context.Request.Path, logger); + await webSocketOptions.OnDisConnected(context, webSocketOptions, context.Request.Path, logger); + } + catch (Exception ex) + { + logger.LogInformation(ex, ex.Message); + } + finally + { + var wsExists = Clients.ContainsKey(context.Connection.Id); + if (wsExists) + { + Clients.TryRemove(context.Connection.Id, out var _); + } + } + } + /// + /// Mvc channel before connection + /// + /// + /// + /// + /// + /// + public virtual async Task MvcChannel_OnBeforeConnection(HttpContext context, WebSocketRouteOption webSocketOptions, string channel, ILogger logger) => await Task.FromResult(true); + /// + /// Mvc channel DisConnectedEvent entry + /// + /// + /// + /// + /// + /// + public virtual async Task MvcChannel_OnDisConnected(HttpContext context, WebSocketRouteOption webSocketOptions, string channel, ILogger logger) + { + await Task.CompletedTask; } + #region Old + + ///// + ///// Forward by WebSocket transfer type + ///// + ///// + ///// + ///// + //private async Task MvcForward(HttpContext context, WebSocket webSocket) + //{ + // var buffer = new byte[ReceiveTextBufferSize]; + // ArraySegment bufferSeg = new ArraySegment(buffer); + + // try + // { + // WebSocketReceiveResult result = await webSocket.ReceiveAsync(bufferSeg, CancellationToken.None); + // //switch (result.MessageType) + // //{ + // // case WebSocketMessageType.Binary: + // // await MvcBinaryForward(context, webSocket, result, buffer); + // // break; + // // case WebSocketMessageType.Text: + // // await MvcTextForward(webSocket, context, result, buffer); + // // break; + // //} + // await MvcForward(webSocket, context, result, bufferSeg); + + // //链接断开 + // await webSocket.CloseAsync(webSocket.CloseStatus == null ? + // webSocket.State == WebSocketState.Aborted ? + // WebSocketCloseStatus.InternalServerError : WebSocketCloseStatus.NormalClosure + // : webSocket.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None); + // } + // catch (OperationCanceledException ex) + // { + // logger.LogInformation($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> 终止接收数据({context.Connection.Id})\r\nStatus:{(webSocket.CloseStatus.HasValue ? webSocket.CloseStatus.ToString() : "ServerClose")}\r\n{ex.Message}"); + // } + //} + + ///// + ///// Handle request content + ///// + ///// + ///// + ///// + ///// + ///// + //private async Task MvcForward(WebSocket webSocket, HttpContext context, WebSocketReceiveResult result, ArraySegment buffer) + //{ + + // long requestTime = DateTime.Now.Ticks; + // StringBuilder json = new StringBuilder(); + + // //处理第一次返回的数据 + // json = json.Append(Encoding.UTF8.GetString(buffer[..result.Count])); + + // //第一次接受已经接受完数据了 + // if (result.EndOfMessage) + // { + // try + // { + // await MvcForwardSendData(webSocket, context, result, json, requestTime); + // } + // catch (Exception ex) + // { + // logger.LogError(ex, ex.Message); + // } + // finally + // { + // json = json.Clear(); + // } + // } + + // //等待客户端发送数据,第二次接受数据 + // while (!result.CloseStatus.HasValue) + // { + // try + // { + // if (!(webSocket.State == WebSocketState.Open || webSocket.State == WebSocketState.CloseSent)) + // { + // break; + // } + + // result = await webSocket.ReceiveAsync(buffer, CancellationToken.None); + // requestTime = DateTime.Now.Ticks; + + // json = json.Append(Encoding.UTF8.GetString(buffer[..result.Count])); + + // if (!result.EndOfMessage || result.CloseStatus.HasValue) + // { + // continue; + // } + + // await MvcForwardSendData(webSocket, context, result, json, requestTime); + + // json = json.Clear(); + // } + // catch (OperationCanceledException ex) + // { + // logger.LogInformation($"{context.Connection.RemoteIpAddress}:{context.Connection.RemotePort} -> 终止接收数据({context.Connection.Id})\r\nStatus:{(webSocket.CloseStatus.HasValue ? webSocket.CloseStatus.ToString() : "ServerClose")}\r\n{ex.Message}"); + // } + // catch (Exception ex) + // { + // logger.LogError(ex, ex.Message); + // } + + // } + + //} + + #endregion #region Newtonsoft.Json @@ -1063,6 +1280,6 @@ public virtual async Task MvcChannel_OnDisconnectioned(HttpContext context, WebS await Task.CompletedTask; } - + #endregion } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcResponseScheme.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcResponseScheme.cs index 00e3681..0335c34 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcResponseScheme.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/Handlers/MvcHandler/MvcResponseScheme.cs @@ -1,7 +1,4 @@ using System; -using System.Collections.Generic; -using System.Runtime.Serialization; -using System.Text; namespace Cyaim.WebSocketServer.Infrastructure.Handlers.MvcHandler { @@ -10,16 +7,6 @@ namespace Cyaim.WebSocketServer.Infrastructure.Handlers.MvcHandler /// public class MvcResponseScheme : IMvcScheme { - /// - /// Response Id with request consistent - /// - public string Id { get; set; } - - /// - /// Target when responding to return requests - /// - public string Target { get; set; } - /// /// Response status. /// Success:0,Application Error:1,NotFoundTarget:2 @@ -37,15 +24,24 @@ public class MvcResponseScheme : IMvcScheme public long RequestTime { get; set; } /// - /// Handle complate time tick + /// Handle complete time tick + /// + public long CompleteTime { get; set; } + + /// + /// Response Id with request consistent + /// + public string Id { get; set; } + + /// + /// Target when responding to return requests /// - public long ComplateTime { get; set; } + public string Target { get; set; } /// /// Response body /// public object Body { get; set; } - } /// @@ -56,9 +52,7 @@ public class MvcResponseSchemeException : Exception /// /// MvcResponseSchemeException /// - public MvcResponseSchemeException() - { - } + public MvcResponseSchemeException() { } /// /// MvcResponseSchemeException @@ -79,14 +73,13 @@ public MvcResponseSchemeException(string message, Exception innerException) : ba Msg = message; } - /// - /// Response Id with request consistent + /// Response Id with request consistent /// public string Id { get; set; } /// - /// Target when responding to return requests + /// Target when responding to return requests /// public string Target { get; set; } @@ -107,8 +100,8 @@ public MvcResponseSchemeException(string message, Exception innerException) : ba public long RequestTime { get; set; } /// - /// Handle complate time tick + /// Handle complete time tick /// - public long ComplateTime { get; set; } + public long CompleteTime { get; set; } } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketManager.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketManager.cs index b0ff5ca..02ef7fa 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketManager.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketManager.cs @@ -16,15 +16,16 @@ public static class WebSocketManager /// /// Default send encoding /// - public static Encoding Encoding { get; set; } = Encoding.UTF8; + private static Encoding Encoding { get; } = Encoding.UTF8; + /// - /// JsonSerialiazerOptions + /// JsonSerializerOptions /// - public static JsonSerializerOptions DefaultMvcJsonSerialiazerOptions { get; set; } = new JsonSerializerOptions + private static JsonSerializerOptions DefaultMvcJsonSerializerOptions { get; } = new JsonSerializerOptions { // 设置为 true 以忽略属性名称的大小写 PropertyNameCaseInsensitive = true, - WriteIndented = false, + WriteIndented = false }; /// @@ -42,7 +43,7 @@ public static async Task SendAsync(MemoryStream buffer, WebSocketMessageType mes { return; } - ParallelLoopResult result = Parallel.ForEach(socket, async (s, state) => + var result = Parallel.ForEach(socket, async (s, state) => { try { @@ -60,10 +61,8 @@ public static async Task SendAsync(MemoryStream buffer, WebSocketMessageType mes // await webSocket.SendAsync(segment, WebSocketMessageType.Text, true, CancellationToken.None); // sent += length; //} - await s.SendAsync(buffer.GetBuffer(), messageType, endOfMessage, cancellationToken); } - } catch (AggregateException age) { @@ -72,18 +71,11 @@ public static async Task SendAsync(MemoryStream buffer, WebSocketMessageType mes Console.WriteLine(item.Message); } } - catch (Exception) - { - - throw; - } }); - while (!result.IsCompleted) { - await Task.Delay(TimeSpan.FromSeconds(10)); + await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); } - } /// @@ -101,7 +93,7 @@ public static async Task SendAsync(ReadOnlyMemory buffer, WebSocketMessage { return; } - ParallelLoopResult result = Parallel.ForEach(socket, async (s, state) => + var result = Parallel.ForEach(socket, async (s, state) => { try { @@ -114,7 +106,6 @@ public static async Task SendAsync(ReadOnlyMemory buffer, WebSocketMessage { await s.SendAsync(buffer, messageType, endOfMessage, cancellationToken); } - } catch (AggregateException age) { @@ -123,18 +114,11 @@ public static async Task SendAsync(ReadOnlyMemory buffer, WebSocketMessage Console.WriteLine(item.Message); } } - catch (Exception) - { - - throw; - } }); - while (!result.IsCompleted) { - await Task.Delay(TimeSpan.FromSeconds(10)); + await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken); } - } /// @@ -155,7 +139,6 @@ public static async Task SendAsync(string data, WebSocketMessageType messageType await SendAsync(encoding.GetBytes(data), messageType, true, CancellationToken.None, socket); } - /// /// Sending serialized model text data without using a buffer /// @@ -166,20 +149,11 @@ public static async Task SendAsync(string data, WebSocketMessageType messageType /// public static async Task SendAsync(this T data, WebSocketMessageType messageType = WebSocketMessageType.Text, params WebSocket[] socket) { - try + if (data == null || socket == null || socket.LongLength < 1) { - if (data == null || socket == null || socket.LongLength < 1) - { - return; - } - - await SendAsync(JsonSerializer.Serialize(data, DefaultMvcJsonSerialiazerOptions), messageType, Encoding, socket); - } - catch (Exception) - { - - throw; + return; } + await SendAsync(JsonSerializer.Serialize(data, DefaultMvcJsonSerializerOptions), messageType, Encoding, socket); } /// @@ -192,22 +166,11 @@ public static async Task SendAsync(this T data, WebSocketMessageType messageT /// public static async Task SendAsync(this WebSocket socket, T data, WebSocketMessageType messageType = WebSocketMessageType.Text) { - try + if (data == null || socket == null) { - if (data == null || socket == null) - { - return; - } - - await SendAsync(JsonSerializer.Serialize(data, DefaultMvcJsonSerialiazerOptions), messageType, Encoding, socket); - } - catch (Exception) - { - - throw; + return; } + await SendAsync(JsonSerializer.Serialize(data, DefaultMvcJsonSerializerOptions), messageType, Encoding, socket); } - - } -} +} \ No newline at end of file diff --git a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketRouteServiceCollectionExtensions.cs b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketRouteServiceCollectionExtensions.cs index d68cc59..9c1a5a7 100644 --- a/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketRouteServiceCollectionExtensions.cs +++ b/Cyaim.WebSocketServer/Cyaim.WebSocketServer/Infrastructure/WebSocketRouteServiceCollectionExtensions.cs @@ -1,17 +1,12 @@ using Cyaim.WebSocketServer.Infrastructure.Attributes; using Cyaim.WebSocketServer.Infrastructure.Configures; -using Microsoft.AspNetCore.Hosting.Server.Features; -using Microsoft.AspNetCore.Hosting.Server; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.DependencyInjection.Extensions; using System; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Reflection; -using System.Security.Authentication.ExtendedProtection; -using System.Text; -using System.Globalization; namespace Cyaim.WebSocketServer.Infrastructure { @@ -27,35 +22,25 @@ public static class WebSocketRouteServiceCollectionExtensions /// public static void ConfigureWebSocketRoute(this IServiceCollection services, Action setupAction) { - if (services == null) { throw new ArgumentNullException(nameof(services)); } - if (setupAction == null) { throw new ArgumentNullException(nameof(setupAction)); } - - WebSocketRouteOption wsrOptions = new WebSocketRouteOption(); + var wsrOptions = new WebSocketRouteOption(); setupAction(wsrOptions); - if (wsrOptions == null) - { - wsrOptions = new WebSocketRouteOption(); - } - if (wsrOptions.ApplicationServiceCollection == null) { - throw new ArgumentNullException("WebSocketRouteOption.ApplicationServiceCollection parameter is required and cannot be null."); + throw new ArgumentNullException(nameof(wsrOptions.ApplicationServiceCollection), "WebSocketRouteOption.ApplicationServiceCollection parameter is required and cannot be null."); } - if (wsrOptions.WebSocketChannels == null || wsrOptions.WebSocketChannels.Count < 1) { Console.WriteLine("WebSocket -> 没有定义WebSocket数据处理通道"); } - - Assembly assembly = null; + Assembly assembly; // 指定标记WebSocket特性的程序集路径,默认为本程序集 if (string.IsNullOrEmpty(wsrOptions?.WatchAssemblyPath)) { @@ -66,7 +51,6 @@ public static void ConfigureWebSocketRoute(this IServiceCollection services, Act { assembly = Assembly.LoadFile(wsrOptions.WatchAssemblyPath); } - if (wsrOptions.WatchAssemblyContext == null) { wsrOptions.WatchAssemblyContext = new WatchAssemblyContext(); @@ -74,101 +58,85 @@ public static void ConfigureWebSocketRoute(this IServiceCollection services, Act #region 计算WebSocketEndPoint - List points = new List(); + var points = new List(); // 在程序集中查询带有指定命名空间前缀的类 - string assemblyName = string.IsNullOrEmpty(wsrOptions.WatchAssemblyNamespacePrefix) ? assembly.FullName.Split()[0]?.Trim(',') + ".Controllers" : wsrOptions.WatchAssemblyNamespacePrefix; + var assemblyName = string.IsNullOrEmpty(wsrOptions.WatchAssemblyNamespacePrefix) ? assembly.FullName.Split()[0]?.Trim(',') + ".Controllers" : wsrOptions.WatchAssemblyNamespacePrefix; var types = assembly.GetTypes().Where(x => !x.IsNestedPrivate && x.FullName.StartsWith(assemblyName)).ToList(); - wsrOptions.WatchAssemblyContext.WatchAssemblyPath = wsrOptions.WatchAssemblyPath; wsrOptions.WatchAssemblyContext.WatchAssemblyTypes = types; - - foreach (Type item in types) + foreach (var item in types) { // 从类提取标记了的方法 - var accessParm = GetClassAccessParm(item); - foreach (WebSocketEndPoint parmItem in accessParm) + var accessParam = GetClassAccessParam(item); + foreach (var paramItem in accessParam) { - if (parmItem == null) + if (paramItem == null) { continue; } - - if (string.IsNullOrEmpty(parmItem.Methods.FirstOrDefault())) + if (string.IsNullOrEmpty(paramItem.Methods.FirstOrDefault())) { - parmItem.Methods = new string[] { parmItem.Action }; + paramItem.Methods = new[] { paramItem.Action }; } // 方法的类名替换Controller - string endPointPath = $"{parmItem.Controller.Replace("Controller", string.Empty)}.{parmItem.Methods.FirstOrDefault()}"; + var endPointPath = $"{paramItem.Controller.Replace("Controller", string.Empty)}.{paramItem.Methods.FirstOrDefault()}"; // 终结点全部小写 - parmItem.MethodPath = endPointPath.ToLower(); - parmItem.Class = item; + paramItem.MethodPath = endPointPath.ToLower(); + paramItem.Class = item; Console.WriteLine($"WebSocket加载成功 -> {endPointPath}"); } - - points.AddRange(accessParm); + points.AddRange(accessParam); } - wsrOptions.WatchAssemblyContext.WatchEndPoint = points.ToArray(); - - wsrOptions.WatchAssemblyContext.WatchMethods = - new ConcurrentDictionary( - wsrOptions.WatchAssemblyContext.WatchEndPoint.ToDictionary(x => x.MethodPath, x => x.MethodInfo)); + new ConcurrentDictionary(wsrOptions.WatchAssemblyContext.WatchEndPoint.ToDictionary(x => x.MethodPath, x => x.MethodInfo)); + #endregion #region 计算构造函数与构造函数中的参数 - Dictionary assConstr = new Dictionary(); - Dictionary assConstrParm = new Dictionary(); - - foreach (Type item in wsrOptions.WatchAssemblyContext.WatchAssemblyTypes) + var assConstr = new Dictionary(); + var assConstrParm = new Dictionary(); + foreach (var item in wsrOptions.WatchAssemblyContext.WatchAssemblyTypes) { - ConstructorInfo[] constructorInfos = item.GetConstructors(BindingFlags.Public | BindingFlags.Instance); - List constructorParameters = new List(); - foreach (var constrItem in constructorInfos) + var constructorInfos = item.GetConstructors(BindingFlags.Public | BindingFlags.Instance); + assConstrParm.Add(item, constructorInfos.Select(constrItem => new ConstructorParameter { - ConstructorParameter constructorParameter = new ConstructorParameter(); - - constructorParameter.ConstructorInfo = constrItem; - constructorParameter.ParameterInfos = constrItem.GetParameters(); - - constructorParameters.Add(constructorParameter); - } - - assConstrParm.Add(item, constructorParameters.ToArray()); - + ConstructorInfo = constrItem, + ParameterInfos = constrItem.GetParameters() + }).ToArray()); assConstr.Add(item, constructorInfos); } wsrOptions.WatchAssemblyContext.AssemblyConstructors = assConstr; - wsrOptions.WatchAssemblyContext.CoustructorParameters = assConstrParm; + wsrOptions.WatchAssemblyContext.ConstructorParameters = assConstrParm; + #endregion #region 计算构造函数里参数最多的 - Dictionary maxAssConstrParm = new Dictionary(); + var maxAssConstrParm = new Dictionary(); foreach (var item in assConstrParm) { var pg = item.Value.GroupBy(x => x.ParameterInfos.Length); - - int maxKey = pg.Select(x => x.Key).Max(); - + var maxKey = pg.Select(x => x.Key).Max(); var temp = pg.FirstOrDefault(x => x.Key == maxKey).FirstOrDefault(); maxAssConstrParm.Add(item.Key, temp); } - wsrOptions.WatchAssemblyContext.MaxCoustructorParameters = maxAssConstrParm; + wsrOptions.WatchAssemblyContext.MaxConstructorParameters = maxAssConstrParm; + #endregion #region 计算类公开方法的参数 - Dictionary methodPamams = new Dictionary(); + var methodPamams = new Dictionary(); foreach (var item in points.Select(x => x.MethodInfo)) { - ParameterInfo[] parameterInfo = item.GetParameters(); - + var parameterInfo = item.GetParameters(); methodPamams.Add(item, parameterInfo); } wsrOptions.WatchAssemblyContext.MethodParameters = methodPamams; + #endregion services.AddSingleton(x => wsrOptions); @@ -180,19 +148,18 @@ public static void ConfigureWebSocketRoute(this IServiceCollection services, Act } // 获取当前线程的默认文化 - CultureInfo defaultCultureInfo = CultureInfo.CurrentCulture; + var defaultCultureInfo = CultureInfo.CurrentCulture; } - /// /// Get assembly controller "WebSocket" EndPoint /// /// /// - public static WebSocketEndPoint[] GetClassAccessParm() + public static WebSocketEndPoint[] GetClassAccessParam() { var type = typeof(T); - return GetClassAccessParm(type); + return GetClassAccessParam(type); } /// @@ -200,33 +167,25 @@ public static WebSocketEndPoint[] GetClassAccessParm() /// /// /// - public static WebSocketEndPoint[] GetClassAccessParm(Type type) + public static WebSocketEndPoint[] GetClassAccessParam(Type type) { var methodLevel = type.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly) - .Select(x => - { - return x.GetCustomAttributes().Select(a => - { - WebSocketEndPoint point = new WebSocketEndPoint(); - point.Action = x.Name; - point.Controller = x.ReflectedType.Name; - point.Methods = new string[] { a.Method }; - point.MethodInfo = x; - - return point; - }).ToArray(); - }).SelectMany((x, y) => x); - IEnumerable points = + .Select(x => x.GetCustomAttributes().Select(a => + new WebSocketEndPoint + { + Action = x.Name, + Controller = x.ReflectedType?.Name, + Methods = new[] { a.Method }, + MethodInfo = x + })).SelectMany((x, y) => x); + var points = methodLevel.GroupBy(x => x.Controller + x.Action).Select(x => - { - WebSocketEndPoint first = x.FirstOrDefault(); - - first.Methods = x.Select(m => m.Methods).SelectMany((y, z) => y).Distinct().ToArray(); - - return first; - }); - + { + var first = x.FirstOrDefault(); + first.Methods = x.Select(m => m.Methods).SelectMany((y, z) => y).Distinct().ToArray(); + return first; + }); return points.ToArray(); } } -} +} \ No newline at end of file