diff --git a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
index e18ce3df56f..fac50c21b7e 100644
--- a/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
+++ b/src/BootstrapBlazor/Extensions/BootstrapBlazorServiceCollectionExtensions.cs
@@ -117,7 +117,6 @@ public static IServiceCollection AddBootstrapBlazor(this IServiceCollection serv
services.AddTabItemBindOptions();
services.AddIconTheme();
- services.AddSocketDataConverters();
return services;
}
@@ -212,29 +211,6 @@ static IServiceCollection AddTabItemBindOptions(this IServiceCollection services
return services;
}
- ///
- /// 增加 Socket 数据转换器集合配置项服务
- ///
- ///
- ///
- static IServiceCollection AddSocketDataConverters(this IServiceCollection services)
- {
- services.AddOptionsMonitor();
- return services;
- }
-
- ///
- /// 配置第三方数据模型与 数据转换器集合配置扩展方法
- ///
- ///
- ///
- ///
- public static IServiceCollection ConfigureSocketDataConverters(this IServiceCollection services, Action configureOptions)
- {
- services.Configure(configureOptions);
- return services;
- }
-
///
/// 配置第三方菜单路由与 Tab 标签页捆绑字典扩展方法
///
diff --git a/src/BootstrapBlazor/Extensions/ITcpSocketClientExtensions.cs b/src/BootstrapBlazor/Extensions/ITcpSocketClientExtensions.cs
deleted file mode 100644
index ccd03c1d31e..00000000000
--- a/src/BootstrapBlazor/Extensions/ITcpSocketClientExtensions.cs
+++ /dev/null
@@ -1,191 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.DependencyInjection;
-using System.Reflection;
-using System.Runtime.Versioning;
-using System.Text;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// 扩展方法类
-///
-[UnsupportedOSPlatform("browser")]
-public static class ITcpSocketClientExtensions
-{
- ///
- /// Sends the specified string content to the connected TCP socket client asynchronously.
- ///
- /// This method converts the provided string content into a byte array using the specified
- /// encoding (or UTF-8 by default) and sends it to the connected TCP socket client. Ensure the client is connected
- /// before calling this method.
- /// The TCP socket client to which the content will be sent. Cannot be .
- /// The string content to send. Cannot be or empty.
- /// The character encoding to use for converting the string content to bytes. If , UTF-8
- /// encoding is used by default.
- /// A to observe while waiting for the operation to complete.
- /// A that represents the asynchronous operation. The result is if the content was sent successfully; otherwise, .
- public static ValueTask SendAsync(this ITcpSocketClient client, string content, Encoding? encoding = null, CancellationToken token = default)
- {
- var buffer = encoding?.GetBytes(content) ?? Encoding.UTF8.GetBytes(content);
- return client.SendAsync(buffer, token);
- }
-
- ///
- /// Establishes an asynchronous connection to the specified host and port.
- ///
- /// The TCP socket client to which the content will be sent. Cannot be .
- /// The hostname or IP address of the server to connect to. Cannot be null or empty.
- /// The port number on the server to connect to. Must be a valid port number between 0 and 65535.
- /// An optional to cancel the connection attempt. Defaults to if not provided.
- /// A task that represents the asynchronous operation. The task result is if the connection
- /// is successfully established; otherwise, .
- public static ValueTask ConnectAsync(this ITcpSocketClient client, string ipString, int port, CancellationToken token = default)
- {
- var endPoint = Utility.ConvertToIpEndPoint(ipString, port);
- return client.ConnectAsync(endPoint, token);
- }
-
- ///
- /// Configures the specified to use the provided
- /// for processing received data and sets a callback to handle processed data.
- ///
- /// This method sets up a two-way data processing pipeline: -
- /// The is configured to pass received data to the
- /// for processing.
- The is configured to invoke
- /// the provided with the processed data.
Use this method
- /// to integrate a custom data processing adapter with a TCP socket client.
- /// The instance to configure.
- /// The used to process incoming data.
- /// A callback function invoked with the processed data. The function receives a
- /// containing the processed data and returns a .
- public static void SetDataPackageAdapter(this ITcpSocketClient client, IDataPackageAdapter adapter, Func, ValueTask> callback)
- {
- // 设置 ITcpSocketClient 的回调函数
- client.ReceivedCallBack = async buffer =>
- {
- // 将接收到的数据传递给 DataPackageAdapter 进行数据处理合规数据触发 ReceivedCallBack 回调
- await adapter.HandlerAsync(buffer);
- };
-
- // 设置 DataPackageAdapter 的回调函数
- adapter.ReceivedCallBack = buffer => callback(buffer);
- }
-
- ///
- /// Configures the specified to use a data package adapter and a callback function
- /// for processing received data.
- ///
- /// This method sets up the to process incoming data using the
- /// specified and . The is called with the converted entity whenever data is received.
- /// The type of the entity that the data will be converted to.
- /// The TCP socket client to configure.
- /// The data package adapter responsible for handling incoming data.
- /// The converter used to transform the received data into the specified entity type.
- /// The callback function to be invoked with the converted entity.
- public static void SetDataPackageAdapter(this ITcpSocketClient client, IDataPackageAdapter adapter, ISocketDataConverter socketDataConverter, Func callback)
- {
- // 设置 ITcpSocketClient 的回调函数
- client.ReceivedCallBack = async buffer =>
- {
- // 将接收到的数据传递给 DataPackageAdapter 进行数据处理合规数据触发 ReceivedCallBack 回调
- await adapter.HandlerAsync(buffer);
- };
-
- // 设置 DataPackageAdapter 的回调函数
- adapter.ReceivedCallBack = async buffer =>
- {
- TEntity? ret = default;
- if (socketDataConverter.TryConvertTo(buffer, out var t))
- {
- ret = t;
- }
- await callback(ret);
- };
- }
-
- ///
- /// Configures the specified to use a custom data package adapter and callback
- /// function.
- ///
- /// This method sets up the to use the specified for handling incoming data. If the type is decorated with a , the associated converter is used to transform the data before invoking
- /// the . The callback is called with the converted entity or if
- /// conversion fails.
- /// The type of entity that the data package adapter will handle.
- /// The TCP socket client to configure.
- /// The data package adapter responsible for processing incoming data.
- /// The callback function to invoke with the processed entity of type .
- public static void SetDataPackageAdapter(this ITcpSocketClient client, IDataPackageAdapter adapter, Func callback)
- {
- // 设置 ITcpSocketClient 的回调函数
- client.ReceivedCallBack = async buffer =>
- {
- // 将接收到的数据传递给 DataPackageAdapter 进行数据处理合规数据触发 ReceivedCallBack 回调
- await adapter.HandlerAsync(buffer);
- };
-
- ISocketDataConverter? converter = null;
-
- var type = typeof(TEntity);
- var converterType = type.GetCustomAttribute();
- if (converterType is { Type: not null })
- {
- // 如果类型上有 SocketDataTypeConverterAttribute 特性则使用特性中指定的转换器
- if (Activator.CreateInstance(converterType.Type) is ISocketDataConverter socketDataConverter)
- {
- converter = socketDataConverter;
- }
- }
- else
- {
- // 如果没有特性则从 ITcpSocketClient 中的服务容器获取转换器
- converter = client.GetSocketDataConverter();
- }
-
- if (converter == null)
- {
- // 设置正常回调
- adapter.ReceivedCallBack = async buffer => await callback(default);
- }
- else
- {
- // 设置转化器
- adapter.SetDataAdapterCallback(converter, callback);
- }
- }
-
- private static void SetDataAdapterCallback(this IDataPackageAdapter adapter, ISocketDataConverter converter, Func callback)
- {
- adapter.ReceivedCallBack = async buffer =>
- {
- TEntity? ret = default;
- if (converter.TryConvertTo(buffer, out var t))
- {
- ret = t;
- }
- await callback(ret);
- };
- }
-
- private static ISocketDataConverter? GetSocketDataConverter(this ITcpSocketClient client)
- {
- ISocketDataConverter? converter = null;
- if (client is IServiceProvider provider)
- {
- var converters = provider.GetRequiredService>().Value;
- if (converters.TryGetTypeConverter(out var v))
- {
- converter = v;
- }
- }
- return converter;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/ISocketDataConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/DataConverter/ISocketDataConverter.cs
deleted file mode 100644
index aaf31b557e7..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/ISocketDataConverter.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Socket 数据转换器接口
-///
-public interface ISocketDataConverter
-{
-
-}
-
-///
-/// Defines a method to convert raw socket data into a specified entity type.
-///
-/// The type of entity to convert the data into.
-public interface ISocketDataConverter : ISocketDataConverter
-{
- ///
- /// Attempts to convert the specified data to an instance of .
- ///
- /// This method does not throw an exception if the conversion fails. Instead, it returns and sets to .
- /// The data to be converted, represented as a read-only memory block of bytes.
- /// When this method returns, contains the converted if the conversion succeeded;
- /// otherwise, .
- /// if the conversion was successful; otherwise, .
- bool TryConvertTo(ReadOnlyMemory data, [NotNullWhen(true)] out TEntity? entity);
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverter.cs
deleted file mode 100644
index 324da0cafa2..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverter.cs
+++ /dev/null
@@ -1,82 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Reflection;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Provides a base class for converting socket data into a specified entity type.
-///
-/// The type of entity to convert the socket data into.
-public class SocketDataConverter(SocketDataConverterCollections converters) : ISocketDataConverter
-{
- ///
- /// 构造函数
- ///
- public SocketDataConverter() : this(new())
- {
-
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public virtual bool TryConvertTo(ReadOnlyMemory data, [NotNullWhen(true)] out TEntity? entity)
- {
- var v = CreateEntity();
- var ret = Parse(data, v);
- entity = ret ? v : default;
- return ret;
- }
-
- ///
- /// 创建实体实例方法
- ///
- ///
- protected virtual TEntity CreateEntity() => Activator.CreateInstance();
-
- ///
- /// 将字节数据转换为指定实体类型的实例。
- ///
- ///
- ///
- protected virtual bool Parse(ReadOnlyMemory data, TEntity entity)
- {
- // 使用 SocketDataPropertyAttribute 特性获取数据转换规则
- var ret = false;
- if (entity != null)
- {
- var unuseProperties = new List(32);
-
- // 通过 SocketDataPropertyConverterAttribute 特性获取属性转换器
- var properties = entity.GetType().GetProperties().Where(p => p.CanWrite).ToList();
- foreach (var p in properties)
- {
- var attr = p.GetCustomAttribute(false)
- ?? GetPropertyConverterAttribute(p);
- if (attr != null)
- {
- p.SetValue(entity, attr.ConvertTo(data));
- }
- }
- ret = true;
- }
- return ret;
- }
-
- private SocketDataPropertyConverterAttribute? GetPropertyConverterAttribute(PropertyInfo propertyInfo)
- {
- SocketDataPropertyConverterAttribute? attr = null;
- if (converters.TryGetPropertyConverter(propertyInfo, out var v))
- {
- attr = v;
- }
- return attr;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverterCollections.cs b/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverterCollections.cs
deleted file mode 100644
index 1651988e988..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataConverterCollections.cs
+++ /dev/null
@@ -1,102 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Collections.Concurrent;
-using System.Linq.Expressions;
-using System.Reflection;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// 数据转换器集合类
-///
-public sealed class SocketDataConverterCollections
-{
- readonly ConcurrentDictionary _converters = new();
- readonly ConcurrentDictionary _propertyConverters = new();
-
- ///
- /// 增加指定 数据类型转换器方法
- ///
- ///
- ///
- public void AddTypeConverter(ISocketDataConverter converter)
- {
- var type = typeof(TEntity);
- _converters.AddOrUpdate(type, t => converter, (t, v) => converter);
- }
-
- ///
- /// 增加默认数据类型转换器方法 转换器使用
- ///
- ///
- public void AddTypeConverter() => AddTypeConverter(new SocketDataConverter(this));
-
- ///
- /// 添加属性类型转化器方法
- ///
- ///
- ///
- ///
- public void AddPropertyConverter(Expression> propertyExpression, SocketDataPropertyConverterAttribute attribute)
- {
- if (propertyExpression.Body is MemberExpression memberExpression)
- {
- if (attribute.Type == null)
- {
- attribute.Type = memberExpression.Type;
- }
- _propertyConverters.AddOrUpdate(memberExpression.Member, m => attribute, (m, v) => attribute);
- }
- }
-
- ///
- /// 获得指定数据类型转换器方法
- ///
- ///
- public bool TryGetTypeConverter([NotNullWhen(true)] out ISocketDataConverter? converter)
- {
- converter = null;
- var ret = false;
- if (_converters.TryGetValue(typeof(TEntity), out var v) && v is ISocketDataConverter c)
- {
- converter = c;
- ret = true;
- }
- return ret;
- }
-
- ///
- /// 获得指定数据类型属性转换器方法
- ///
- ///
- public bool TryGetPropertyConverter(Expression> propertyExpression, [NotNullWhen(true)] out SocketDataPropertyConverterAttribute? converterAttribute)
- {
- converterAttribute = null;
- var ret = false;
- if (propertyExpression.Body is MemberExpression memberExpression && TryGetPropertyConverter(memberExpression.Member, out var v))
- {
- converterAttribute = v;
- ret = true;
- }
- return ret;
- }
-
- ///
- /// 获得指定数据类型属性转换器方法
- ///
- ///
- public bool TryGetPropertyConverter(MemberInfo memberInfo, [NotNullWhen(true)] out SocketDataPropertyConverterAttribute? converterAttribute)
- {
- converterAttribute = null;
- var ret = false;
- if (_propertyConverters.TryGetValue(memberInfo, out var v))
- {
- converterAttribute = v;
- ret = true;
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataPropertyConverterAttribute.cs b/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataPropertyConverterAttribute.cs
deleted file mode 100644
index a8f171e5fd3..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataPropertyConverterAttribute.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Represents an attribute used to mark a field as a socket data field.
-///
-/// This attribute can be applied to fields to indicate that they are part of the data transmitted over a
-/// socket connection. It is intended for use in scenarios where socket communication requires specific fields to be
-/// identified for processing.
-[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
-public class SocketDataPropertyConverterAttribute : Attribute
-{
- ///
- /// 获得/设置 数据类型
- ///
- public Type? Type { get; set; }
-
- ///
- /// 获得/设置 数据偏移量
- ///
- public int Offset { get; set; }
-
- ///
- /// 获得/设置 数据长度
- ///
- public int Length { get; set; }
-
- ///
- /// 获得/设置 数据编码名称
- ///
- public string? EncodingName { get; set; }
-
- ///
- /// 获得/设置 数据转换器类型
- ///
- public Type? ConverterType { get; set; }
-
- ///
- /// 获得/设置 数据转换器构造函数参数
- ///
- public object?[]? ConverterParameters { get; set; }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataTypeConverterAttribute.cs b/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataTypeConverterAttribute.cs
deleted file mode 100644
index 61b33a1ed31..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataConverter/SocketDataTypeConverterAttribute.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-///
-///
-[AttributeUsage(AttributeTargets.Class)]
-public class SocketDataTypeConverterAttribute : Attribute
-{
- ///
- /// Gets or sets the type of the .
- ///
- public Type? Type { get; set; }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataPackageAdapter/DataPackageAdapter.cs b/src/BootstrapBlazor/Services/TcpSocket/DataPackageAdapter/DataPackageAdapter.cs
deleted file mode 100644
index 77733014514..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataPackageAdapter/DataPackageAdapter.cs
+++ /dev/null
@@ -1,81 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Provides a base implementation for adapting data packages between different systems or formats.
-///
-/// This abstract class serves as a foundation for implementing custom data package adapters. It defines
-/// common methods for sending, receiving, and handling data packages, as well as a property for accessing the
-/// associated data package handler. Derived classes should override the virtual methods to provide specific behavior
-/// for handling data packages.
-public class DataPackageAdapter : IDataPackageAdapter
-{
- ///
- ///
- ///
- public Func, ValueTask>? ReceivedCallBack { get; set; }
-
- ///
- ///
- ///
- public IDataPackageHandler? DataPackageHandler { get; set; }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public virtual async ValueTask HandlerAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- if (DataPackageHandler != null)
- {
- if (DataPackageHandler.ReceivedCallBack == null)
- {
- DataPackageHandler.ReceivedCallBack = OnHandlerReceivedCallBack;
- }
-
- // 如果存在数据处理器则调用其处理方法
- await DataPackageHandler.HandlerAsync(data, token);
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public virtual bool TryConvertTo(ReadOnlyMemory data, ISocketDataConverter socketDataConverter, out TEntity? entity)
- {
- entity = default;
- var ret = socketDataConverter.TryConvertTo(data, out var v);
- if (ret)
- {
- entity = v;
- }
- return ret;
- }
-
- ///
- /// Handles incoming data by invoking a callback method, if one is defined.
- ///
- /// This method is designed to be overridden in derived classes to provide custom handling of
- /// incoming data. If a callback method is assigned, it will be invoked asynchronously with the provided
- /// data.
- /// The incoming data to be processed, represented as a read-only memory block of bytes.
- ///
- protected virtual async ValueTask OnHandlerReceivedCallBack(ReadOnlyMemory data)
- {
- if (ReceivedCallBack != null)
- {
- // 调用接收回调方法处理数据
- await ReceivedCallBack(data);
- }
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataPackageAdapter/IDataPackageAdapter.cs b/src/BootstrapBlazor/Services/TcpSocket/DataPackageAdapter/IDataPackageAdapter.cs
deleted file mode 100644
index e37d9272495..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataPackageAdapter/IDataPackageAdapter.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Defines an adapter for handling and transmitting data packages to a target destination.
-///
-/// This interface provides methods for sending data asynchronously and configuring a data handler.
-/// Implementations of this interface are responsible for managing the interaction between the caller and the underlying
-/// data transmission mechanism.
-public interface IDataPackageAdapter
-{
- ///
- /// Gets or sets the callback function to be invoked when data is received.
- ///
- /// The callback function is expected to handle the received data asynchronously. Ensure that the
- /// implementation of the callback does not block the calling thread and completes promptly to avoid performance
- /// issues.
- Func, ValueTask>? ReceivedCallBack { get; set; }
-
- ///
- /// Gets the handler responsible for processing data packages.
- ///
- IDataPackageHandler? DataPackageHandler { get; }
-
- ///
- /// Asynchronously receives data from a source and processes it.
- ///
- /// This method does not return any result directly. It is intended for scenarios where data is received
- /// and processed asynchronously. Ensure that the parameter contains valid data before calling
- /// this method.
- /// A read-only memory region containing the data to be received. The caller must ensure the memory is valid and
- /// populated.
- /// An optional cancellation token that can be used to cancel the operation. Defaults to if
- /// not provided.
- /// A representing the asynchronous operation. The task completes when the data has been
- /// successfully received and processed.
- ValueTask HandlerAsync(ReadOnlyMemory data, CancellationToken token = default);
-
- ///
- /// Attempts to convert the specified byte data into an entity of type .
- ///
- /// This method does not throw an exception if the conversion fails. Instead, it returns and sets to its default value.
- /// The type of the entity to convert the data to.
- /// The byte data to be converted.
- /// The converter used to transform the byte data into an entity.
- /// When this method returns, contains the converted entity if the conversion was successful; otherwise, the default
- /// value for the type of the entity.
- /// if the conversion was successful; otherwise, .
- bool TryConvertTo(ReadOnlyMemory data, ISocketDataConverter socketDataConverter, out TEntity? entity);
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/DataPackageHandlerBase.cs b/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/DataPackageHandlerBase.cs
deleted file mode 100644
index 41677e72a7b..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/DataPackageHandlerBase.cs
+++ /dev/null
@@ -1,69 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Provides a base implementation for handling data packages in a communication system.
-///
-/// This abstract class defines the core contract for receiving and sending data packages. Derived
-/// classes should override and extend its functionality to implement specific data handling logic. The default
-/// implementation simply returns the provided data.
-public abstract class DataPackageHandlerBase : IDataPackageHandler
-{
- private Memory _lastReceiveBuffer = Memory.Empty;
-
- ///
- ///
- ///
- public Func, ValueTask>? ReceivedCallBack { get; set; }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public abstract ValueTask HandlerAsync(ReadOnlyMemory data, CancellationToken token = default);
-
- ///
- /// Handles the processing of a sticky package by adjusting the provided buffer and length.
- ///
- /// This method processes the portion of the buffer beyond the specified length and updates the
- /// internal state accordingly. The caller must ensure that the contains sufficient data
- /// for the specified .
- /// The memory buffer containing the data to process.
- /// The length of the valid data within the buffer.
- protected void SlicePackage(ReadOnlyMemory buffer, int length)
- {
- _lastReceiveBuffer = buffer[length..].ToArray().AsMemory();
- }
-
- ///
- /// Concatenates the provided buffer with any previously stored data and returns the combined result.
- ///
- /// This method combines the provided buffer with any data stored in the internal buffer. After
- /// concatenation, the internal buffer is cleared. The returned memory block is allocated from a shared memory pool
- /// and should be used promptly to avoid holding onto pooled resources.
- /// The buffer to concatenate with the previously stored data. Must not be empty.
- /// A instance containing the concatenated data. If no previously stored data exists, the
- /// method returns the input .
- protected ReadOnlyMemory ConcatBuffer(ReadOnlyMemory buffer)
- {
- if (_lastReceiveBuffer.IsEmpty)
- {
- return buffer;
- }
-
- // 计算缓存区长度
- Memory merged = new byte[_lastReceiveBuffer.Length + buffer.Length];
- _lastReceiveBuffer.CopyTo(merged);
- buffer.CopyTo(merged[_lastReceiveBuffer.Length..]);
-
- // Clear the sticky buffer
- _lastReceiveBuffer = Memory.Empty;
- return merged;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/DelimiterDataPackageHandler.cs b/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/DelimiterDataPackageHandler.cs
deleted file mode 100644
index e8923643006..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/DelimiterDataPackageHandler.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers;
-using System.Text;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Handles data packages that are delimited by a specific sequence of bytes or characters.
-///
-/// This class provides functionality for processing data packages that are separated by a defined
-/// delimiter. The delimiter can be specified as a string with an optional encoding or as a byte array.
-public class DelimiterDataPackageHandler : DataPackageHandlerBase
-{
- private readonly ReadOnlyMemory _delimiter;
-
- ///
- /// Initializes a new instance of the class with the specified delimiter
- /// and optional encoding.
- ///
- /// The string delimiter used to separate data packages. This value cannot be null or empty.
- /// The character encoding used to convert the delimiter to bytes. If null, is used as
- /// the default.
- /// Thrown if is null or empty.
- public DelimiterDataPackageHandler(string delimiter, Encoding? encoding = null)
- {
- if (string.IsNullOrEmpty(delimiter))
- {
- throw new ArgumentNullException(nameof(delimiter), "Delimiter cannot be null or empty.");
- }
-
- encoding ??= Encoding.UTF8;
- _delimiter = encoding.GetBytes(delimiter);
- }
-
- ///
- /// Initializes a new instance of the class with the specified delimiters.
- ///
- /// An array of bytes representing the delimiters used to parse data packages. Cannot be .
- /// Thrown if is .
- public DelimiterDataPackageHandler(byte[] delimiter)
- {
- _delimiter = delimiter ?? throw new ArgumentNullException(nameof(delimiter), "Delimiter cannot be null.");
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public override async ValueTask HandlerAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- data = ConcatBuffer(data);
-
- while (data.Length > 0)
- {
- var index = data.Span.IndexOfAny(_delimiter.Span);
- var segment = index == -1 ? data : data[..index];
- var length = segment.Length + _delimiter.Length;
- using var buffer = MemoryPool.Shared.Rent(length);
- segment.CopyTo(buffer.Memory);
-
- if (index != -1)
- {
- SlicePackage(data, index + _delimiter.Length);
-
- _delimiter.CopyTo(buffer.Memory[index..]);
- if (ReceivedCallBack != null)
- {
- await ReceivedCallBack(buffer.Memory[..length].ToArray());
- }
-
- data = data[(index + _delimiter.Length)..];
- }
- else
- {
- SlicePackage(data, 0);
- break;
- }
- }
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/FixLengthDataPackageHandler.cs b/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/FixLengthDataPackageHandler.cs
deleted file mode 100644
index 40289ace4ff..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/FixLengthDataPackageHandler.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Handles fixed-length data packages by processing incoming data of a specified length.
-///
-/// This class is designed to handle data packages with a fixed length, as specified during
-/// initialization. It extends and overrides its behavior to process fixed-length
-/// data.
-/// The data package total data length.
-public class FixLengthDataPackageHandler(int length) : DataPackageHandlerBase
-{
- private readonly Memory _data = new byte[length];
-
- private int _receivedLength;
-
- ///
- ///
- ///
- ///
- ///
- ///
- public override async ValueTask HandlerAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- while (data.Length > 0)
- {
- // 拷贝数据
- var len = length - _receivedLength;
- var segment = data.Length > len ? data[..len] : data;
- segment.CopyTo(_data[_receivedLength..]);
-
- // 更新数据
- data = data[segment.Length..];
-
- // 更新已接收长度
- _receivedLength += segment.Length;
-
- // 如果已接收长度等于总长度则触发回调
- if (_receivedLength == length)
- {
- // 重置已接收长度
- _receivedLength = 0;
- if (ReceivedCallBack != null)
- {
- await ReceivedCallBack(_data);
- }
- }
- }
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/IDataPackageHandler.cs b/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/IDataPackageHandler.cs
deleted file mode 100644
index 25dbd85f445..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DataPackageHandler/IDataPackageHandler.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Defines an interface for adapting data packages to and from a TCP socket connection.
-///
-/// Implementations of this interface are responsible for converting raw data received from a TCP socket
-/// into structured data packages and vice versa. This allows for custom serialization and deserialization logic
-/// tailored to specific application protocols.
-public interface IDataPackageHandler
-{
- ///
- /// Gets or sets the callback function to be invoked when data is received asynchronously.
- ///
- Func, ValueTask>? ReceivedCallBack { get; set; }
-
- ///
- /// Asynchronously receives data and processes it.
- ///
- /// The method is designed for asynchronous operations and may be used in scenarios where
- /// efficient handling of data streams is required. Ensure that the parameter contains valid
- /// data for processing, and handle potential cancellation using the .
- /// The data to be received, represented as a read-only memory block of bytes.
- /// A cancellation token that can be used to cancel the operation. Defaults to if not
- /// provided.
- /// A containing if the data was successfully received and
- /// processed; otherwise, .
- ValueTask HandlerAsync(ReadOnlyMemory data, CancellationToken token = default);
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DefaultSocketClientProvider.cs b/src/BootstrapBlazor/Services/TcpSocket/DefaultSocketClientProvider.cs
deleted file mode 100644
index b07cca71607..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DefaultSocketClientProvider.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Net;
-using System.Net.Sockets;
-using System.Runtime.Versioning;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// TcpSocket 客户端默认实现
-///
-[UnsupportedOSPlatform("browser")]
-class DefaultSocketClientProvider : ISocketClientProvider
-{
- private TcpClient? _client;
-
- ///
- ///
- ///
- public bool IsConnected => _client?.Connected ?? false;
-
- ///
- ///
- ///
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
-
- ///
- ///
- ///
- public async ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- _client = new TcpClient(LocalEndPoint);
- await _client.ConnectAsync(endPoint, token).ConfigureAwait(false);
- if (_client.Connected)
- {
- if (_client.Client.LocalEndPoint is IPEndPoint localEndPoint)
- {
- LocalEndPoint = localEndPoint;
- }
- }
- return _client.Connected;
- }
-
- ///
- ///
- ///
- public async ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- var ret = false;
- if (_client != null)
- {
- var stream = _client.GetStream();
- await stream.WriteAsync(data, token).ConfigureAwait(false);
- ret = true;
- }
- return ret;
- }
-
- ///
- ///
- ///
- public async ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- var len = 0;
- if (_client is { Connected: true })
- {
- var stream = _client.GetStream();
- len = await stream.ReadAsync(buffer, token).ConfigureAwait(false);
-
- if (len == 0)
- {
- _client.Close();
- }
- }
- return len;
- }
-
- ///
- ///
- ///
- public ValueTask CloseAsync()
- {
- if (_client != null)
- {
- _client.Close();
- _client = null;
- }
- return ValueTask.CompletedTask;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DefaultTcpSocketClient.cs b/src/BootstrapBlazor/Services/TcpSocket/DefaultTcpSocketClient.cs
deleted file mode 100644
index 8c84d7a538f..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DefaultTcpSocketClient.cs
+++ /dev/null
@@ -1,441 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using System.Buffers;
-using System.Net;
-using System.Runtime.Versioning;
-
-namespace BootstrapBlazor.Components;
-
-[UnsupportedOSPlatform("browser")]
-class DefaultTcpSocketClient(SocketClientOptions options) : IServiceProvider, ITcpSocketClient
-{
- ///
- /// Gets or sets the socket client provider used for managing socket connections.
- ///
- private ISocketClientProvider? SocketClientProvider { get; set; }
-
- ///
- /// Gets or sets the logger instance used for logging messages and events.
- ///
- private ILogger? Logger { get; set; }
-
- ///
- /// Gets or sets the service provider used to resolve dependencies.
- ///
- [NotNull]
- public IServiceProvider? ServiceProvider { get; set; }
-
- ///
- ///
- ///
- public SocketClientOptions Options => options;
-
- ///
- ///
- ///
- public bool IsConnected => SocketClientProvider?.IsConnected ?? false;
-
- ///
- ///
- ///
- public IPEndPoint LocalEndPoint => SocketClientProvider?.LocalEndPoint ?? new IPEndPoint(IPAddress.Any, 0);
-
- ///
- ///
- ///
- public Func, ValueTask>? ReceivedCallBack { get; set; }
-
- ///
- ///
- ///
- public Func? OnConnecting { get; set; }
-
- ///
- ///
- ///
- public Func? OnConnected { get; set; }
-
- private IPEndPoint? _remoteEndPoint;
- private IPEndPoint? _localEndPoint;
- private CancellationTokenSource? _receiveCancellationTokenSource;
- private CancellationTokenSource? _autoConnectTokenSource;
-
- private readonly SemaphoreSlim _semaphoreSlim = new(1, 1);
-
- ///
- ///
- ///
- ///
- ///
- ///
- public async ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- if (IsConnected)
- {
- return true;
- }
-
- var connectionToken = GenerateConnectionToken(token);
- try
- {
- await _semaphoreSlim.WaitAsync(connectionToken).ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- // 如果信号量等待被取消,则直接返回 IsConnected
- // 不管是超时还是被取消,都不需要重连,肯定有其他线程在连接中
- return IsConnected;
- }
-
- if (IsConnected)
- {
- _semaphoreSlim.Release();
- return true;
- }
-
- var reconnect = true;
- var ret = false;
- SocketClientProvider = ServiceProvider?.GetRequiredService()
- ?? throw new InvalidOperationException("SocketClientProvider is not registered in the service provider.");
-
- try
- {
- if (OnConnecting != null)
- {
- await OnConnecting();
- }
- ret = await ConnectCoreAsync(SocketClientProvider, endPoint, connectionToken);
- if (OnConnected != null)
- {
- await OnConnected();
- }
- }
- catch (OperationCanceledException ex)
- {
- if (token.IsCancellationRequested)
- {
- Log(LogLevel.Warning, ex, $"TCP Socket connect operation was canceled from {LocalEndPoint} to {endPoint}");
- reconnect = false;
- }
- else
- {
- Log(LogLevel.Warning, ex, $"TCP Socket connect operation timed out from {LocalEndPoint} to {endPoint}");
- }
- }
- catch (Exception ex)
- {
- Log(LogLevel.Error, ex, $"TCP Socket connection failed from {LocalEndPoint} to {endPoint}");
- }
-
- // 释放信号量
- _semaphoreSlim.Release();
-
- if (reconnect)
- {
- _autoConnectTokenSource = new();
-
- if (!ret)
- {
- Reconnect();
- }
- }
- return ret;
- }
-
- private void Reconnect()
- {
- if (_autoConnectTokenSource != null && options.IsAutoReconnect && _remoteEndPoint != null)
- {
- Task.Run(async () =>
- {
- try
- {
- await Task.Delay(options.ReconnectInterval, _autoConnectTokenSource.Token).ConfigureAwait(false);
- await ConnectAsync(_remoteEndPoint, _autoConnectTokenSource.Token).ConfigureAwait(false);
- }
- catch { }
- }, CancellationToken.None).ConfigureAwait(false);
- }
- }
-
- private async ValueTask ConnectCoreAsync(ISocketClientProvider provider, IPEndPoint endPoint, CancellationToken token)
- {
- // 释放资源
- await CloseCoreAsync();
-
- // 创建新的 TcpClient 实例
- provider.LocalEndPoint = Options.LocalEndPoint;
-
- _localEndPoint = Options.LocalEndPoint;
- _remoteEndPoint = endPoint;
-
- var ret = await provider.ConnectAsync(endPoint, token);
-
- if (ret)
- {
- _localEndPoint = provider.LocalEndPoint;
-
- if (options.IsAutoReceive)
- {
- _ = Task.Run(AutoReceiveAsync, CancellationToken.None).ConfigureAwait(false);
- }
- }
- return ret;
- }
-
- private CancellationToken GenerateConnectionToken(CancellationToken token)
- {
- var connectionToken = token;
- if (Options.ConnectTimeout > 0)
- {
- // 设置连接超时时间
- var connectTokenSource = new CancellationTokenSource(options.ConnectTimeout);
- connectionToken = CancellationTokenSource.CreateLinkedTokenSource(token, connectTokenSource.Token).Token;
- }
- return connectionToken;
- }
-
- ///
- ///
- ///
- ///
- ///
- ///
- public async ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- if (SocketClientProvider is not { IsConnected: true })
- {
- throw new InvalidOperationException($"TCP Socket is not connected {LocalEndPoint}");
- }
-
- var ret = false;
- var reconnect = true;
- try
- {
- var sendToken = token;
- if (options.SendTimeout > 0)
- {
- // 设置发送超时时间
- var sendTokenSource = new CancellationTokenSource(options.SendTimeout);
- sendToken = CancellationTokenSource.CreateLinkedTokenSource(token, sendTokenSource.Token).Token;
- }
- ret = await SocketClientProvider.SendAsync(data, sendToken);
- }
- catch (OperationCanceledException ex)
- {
- if (token.IsCancellationRequested)
- {
- reconnect = false;
- Log(LogLevel.Warning, ex, $"TCP Socket send operation was canceled from {_localEndPoint} to {_remoteEndPoint}");
- }
- else
- {
- Log(LogLevel.Warning, ex, $"TCP Socket send operation timed out from {_localEndPoint} to {_remoteEndPoint}");
- }
- }
- catch (Exception ex)
- {
- Log(LogLevel.Error, ex, $"TCP Socket send failed from {_localEndPoint} to {_remoteEndPoint}");
- }
-
- Log(LogLevel.Information, null, $"Sending data from {_localEndPoint} to {_remoteEndPoint}, Data Length: {data.Length} Data Content: {BitConverter.ToString(data.ToArray())} Result: {ret}");
-
- if (!ret && reconnect)
- {
- // 如果发送失败并且需要重连则尝试重连
- Reconnect();
- }
- return ret;
- }
-
- ///
- ///
- ///
- ///
- ///
- public async ValueTask> ReceiveAsync(CancellationToken token = default)
- {
- if (SocketClientProvider is not { IsConnected: true })
- {
- throw new InvalidOperationException($"TCP Socket is not connected {LocalEndPoint}");
- }
-
- if (options.IsAutoReceive)
- {
- throw new InvalidOperationException("Cannot call ReceiveAsync when IsAutoReceive is true. Use the auto-receive mechanism instead.");
- }
-
- using var block = MemoryPool.Shared.Rent(options.ReceiveBufferSize);
- var buffer = block.Memory;
- var len = await ReceiveCoreAsync(SocketClientProvider, buffer, token);
- if (len == 0)
- {
- Reconnect();
- }
- return buffer[..len];
- }
-
- private async ValueTask AutoReceiveAsync()
- {
- // 自动接收方法
- _receiveCancellationTokenSource ??= new();
- while (_receiveCancellationTokenSource is { IsCancellationRequested: false })
- {
- if (SocketClientProvider is not { IsConnected: true })
- {
- throw new InvalidOperationException($"TCP Socket is not connected {LocalEndPoint}");
- }
-
- using var block = MemoryPool.Shared.Rent(options.ReceiveBufferSize);
- var buffer = block.Memory;
- var len = await ReceiveCoreAsync(SocketClientProvider, buffer, _receiveCancellationTokenSource.Token);
- if (len == 0)
- {
- // 远端关闭或者 DisposeAsync 方法被调用时退出
- break;
- }
- }
-
- Reconnect();
- }
-
- private async ValueTask ReceiveCoreAsync(ISocketClientProvider client, Memory buffer, CancellationToken token)
- {
- var reconnect = true;
- var len = 0;
- try
- {
- var receiveToken = token;
- if (options.ReceiveTimeout > 0)
- {
- // 设置接收超时时间
- var receiveTokenSource = new CancellationTokenSource(options.ReceiveTimeout);
- receiveToken = CancellationTokenSource.CreateLinkedTokenSource(receiveToken, receiveTokenSource.Token).Token;
- }
-
- len = await client.ReceiveAsync(buffer, receiveToken);
- if (len == 0)
- {
- // 远端主机关闭链路
- Log(LogLevel.Information, null, $"TCP Socket {_localEndPoint} received 0 data closed by {_remoteEndPoint}");
- buffer = Memory.Empty;
- }
- else
- {
- buffer = buffer[..len];
- }
-
- if (ReceivedCallBack != null)
- {
- // 如果订阅回调则触发回调
- await ReceivedCallBack(buffer);
- }
- }
- catch (OperationCanceledException ex)
- {
- if (token.IsCancellationRequested)
- {
- Log(LogLevel.Warning, ex, $"TCP Socket receive operation canceled from {_localEndPoint} to {_remoteEndPoint}");
- reconnect = false;
- }
- else
- {
- Log(LogLevel.Warning, ex, $"TCP Socket receive operation timed out from {_localEndPoint} to {_remoteEndPoint}");
- }
- }
- catch (Exception ex)
- {
- Log(LogLevel.Error, ex, $"TCP Socket receive failed from {_localEndPoint} to {_remoteEndPoint}");
- }
-
- Log(LogLevel.Information, null, $"Receiving data from {_localEndPoint} to {_remoteEndPoint}, Data Length: {len} Data Content: {BitConverter.ToString(buffer.ToArray())}");
-
- if (len == 0 && reconnect)
- {
- // 如果接收数据长度为 0 并且需要重连则尝试重连
- Reconnect();
- }
- return len;
- }
-
- ///
- /// Logs a message with the specified log level, exception, and additional context.
- ///
- private void Log(LogLevel logLevel, Exception? ex, string? message)
- {
- if (options.EnableLog)
- {
- Logger ??= ServiceProvider?.GetRequiredService>();
- Logger?.Log(logLevel, ex, "{Message}", message);
- }
- }
-
- ///
- ///
- ///
- public async ValueTask CloseAsync()
- {
- // 取消重连任务
- if (_autoConnectTokenSource != null)
- {
- _autoConnectTokenSource.Cancel();
- _autoConnectTokenSource.Dispose();
- _autoConnectTokenSource = null;
- }
-
- await CloseCoreAsync();
- }
-
- private async ValueTask CloseCoreAsync()
- {
- // 取消接收数据的任务
- if (_receiveCancellationTokenSource != null)
- {
- _receiveCancellationTokenSource.Cancel();
- _receiveCancellationTokenSource.Dispose();
- _receiveCancellationTokenSource = null;
- }
-
- if (SocketClientProvider != null)
- {
- await SocketClientProvider.CloseAsync();
- }
- }
-
- ///
- ///
- ///
- ///
- ///
- public object? GetService(Type serviceType) => ServiceProvider.GetService(serviceType);
-
- ///
- /// Releases the resources used by the current instance of the class.
- ///
- /// This method is called to free both managed and unmanaged resources. If the parameter is , the method releases managed resources in addition to
- /// unmanaged resources. Override this method in a derived class to provide custom cleanup logic.
- /// to release both managed and unmanaged resources; to release only
- /// unmanaged resources.
- private async ValueTask DisposeAsync(bool disposing)
- {
- if (disposing)
- {
- await CloseAsync();
- }
- }
-
- ///
- ///
- ///
- public async ValueTask DisposeAsync()
- {
- await DisposeAsync(true);
- GC.SuppressFinalize(this);
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/DefaultTcpSocketFactory.cs b/src/BootstrapBlazor/Services/TcpSocket/DefaultTcpSocketFactory.cs
deleted file mode 100644
index 55f8815c58c..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/DefaultTcpSocketFactory.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Collections.Concurrent;
-using System.Runtime.Versioning;
-
-namespace BootstrapBlazor.Components;
-
-[UnsupportedOSPlatform("browser")]
-sealed class DefaultTcpSocketFactory(IServiceProvider provider) : ITcpSocketFactory
-{
- private readonly ConcurrentDictionary _pool = new();
-
- public ITcpSocketClient GetOrCreate(string name, Action valueFactory)
- {
- return _pool.GetOrAdd(name, key =>
- {
- var options = new SocketClientOptions();
- valueFactory(options);
- var client = new DefaultTcpSocketClient(options)
- {
- ServiceProvider = provider,
- };
- return client;
- });
- }
-
- public ITcpSocketClient? Remove(string name)
- {
- ITcpSocketClient? client = null;
- if (_pool.TryRemove(name, out var c))
- {
- client = c;
- }
- return client;
- }
-
- private async ValueTask DisposeAsync(bool disposing)
- {
- if (disposing)
- {
- // 释放托管资源
- foreach (var socket in _pool.Values)
- {
- await socket.DisposeAsync();
- }
- _pool.Clear();
- }
- }
-
- ///
- ///
- ///
- public async ValueTask DisposeAsync()
- {
- await DisposeAsync(true);
- GC.SuppressFinalize(this);
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/Extensions/SocketDataPropertyExtensions.cs b/src/BootstrapBlazor/Services/TcpSocket/Extensions/SocketDataPropertyExtensions.cs
deleted file mode 100644
index dbfe1f7f4a3..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/Extensions/SocketDataPropertyExtensions.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-static class SocketDataPropertyExtensions
-{
- public static ISocketDataPropertyConverter? GetConverter(this SocketDataPropertyConverterAttribute attribute)
- {
- return attribute.GetConverterByType() ?? attribute.GetDefaultConverter();
- }
-
- private static ISocketDataPropertyConverter? GetConverterByType(this SocketDataPropertyConverterAttribute attribute)
- {
- ISocketDataPropertyConverter? converter = null;
- var converterType = attribute.ConverterType;
- if (converterType != null)
- {
- var converterParameters = attribute.ConverterParameters;
- var c = Activator.CreateInstance(converterType, converterParameters);
- if(c is ISocketDataPropertyConverter v)
- {
- converter = v;
- }
- }
- return converter;
- }
-
- private static ISocketDataPropertyConverter? GetDefaultConverter(this SocketDataPropertyConverterAttribute attribute)
- {
- ISocketDataPropertyConverter? converter = null;
- var type = attribute.Type;
- if (type != null)
- {
- if (type == typeof(byte[]))
- {
- converter = new SocketDataByteArrayConverter();
- }
- else if (type == typeof(string))
- {
- converter = new SocketDataStringConverter(attribute.EncodingName);
- }
- else if (type.IsEnum)
- {
- converter = new SocketDataEnumConverter(attribute.Type);
- }
- else if (type == typeof(bool))
- {
- converter = new SocketDataBoolConverter();
- }
- else if (type == typeof(short))
- {
- converter = new SocketDataInt16BigEndianConverter();
- }
- else if (type == typeof(int))
- {
- converter = new SocketDataInt32BigEndianConverter();
- }
- else if (type == typeof(long))
- {
- converter = new SocketDataInt64BigEndianConverter();
- }
- else if (type == typeof(float))
- {
- converter = new SocketDataSingleBigEndianConverter();
- }
- else if (type == typeof(double))
- {
- converter = new SocketDataDoubleBigEndianConverter();
- }
- else if (type == typeof(ushort))
- {
- converter = new SocketDataUInt16BigEndianConverter();
- }
- else if (type == typeof(uint))
- {
- converter = new SocketDataUInt32BigEndianConverter();
- }
- else if (type == typeof(ulong))
- {
- converter = new SocketDataUInt64BigEndianConverter();
- }
- }
- return converter;
- }
-
- public static object? ConvertTo(this SocketDataPropertyConverterAttribute attribute, ReadOnlyMemory data)
- {
- object? ret = null;
- var start = attribute.Offset;
- var length = attribute.Length;
-
- if (data.Length >= start + length)
- {
- var buffer = data.Slice(start, length);
- var converter = attribute.GetConverter();
- if (converter != null)
- {
- ret = converter.Convert(buffer);
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/Extensions/TcpSocketExtensions.cs b/src/BootstrapBlazor/Services/TcpSocket/Extensions/TcpSocketExtensions.cs
deleted file mode 100644
index dde3bc7aa8f..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/Extensions/TcpSocketExtensions.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.DependencyInjection.Extensions;
-using System.Runtime.Versioning;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// TcpSocket 扩展方法
-///
-[UnsupportedOSPlatform("browser")]
-public static class TcpSocketExtensions
-{
- ///
- /// 增加 ITcpSocketFactory 服务
- ///
- ///
- ///
- public static IServiceCollection AddBootstrapBlazorTcpSocketFactory(this IServiceCollection services)
- {
- // 添加 ITcpSocketFactory 服务
- services.AddSingleton();
-
- // 增加 ISocketClientProvider 服务
- services.TryAddTransient();
- return services;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/ISocketClientProvider.cs b/src/BootstrapBlazor/Services/TcpSocket/ISocketClientProvider.cs
deleted file mode 100644
index 6c3bd9e862b..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/ISocketClientProvider.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Net;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Defines the contract for a socket client that provides asynchronous methods for connecting, sending, receiving, and
-/// closing network connections.
-///
-/// This interface is designed to facilitate network communication using sockets. It provides methods for
-/// establishing connections, transmitting data, and receiving data asynchronously. Implementations of this interface
-/// should ensure proper resource management, including closing connections and releasing resources when no longer
-/// needed.
-public interface ISocketClientProvider
-{
- ///
- /// Gets a value indicating whether the connection is currently active.
- ///
- bool IsConnected { get; }
-
- ///
- /// Gets the local network endpoint that the socket is bound to.
- ///
- IPEndPoint LocalEndPoint { get; set; }
-
- ///
- /// Establishes an asynchronous connection to the specified endpoint.
- ///
- /// This method attempts to establish a connection to the specified endpoint. If the connection
- /// fails, the method returns rather than throwing an exception. Ensure the endpoint is
- /// valid and reachable before calling this method.
- /// The representing the remote endpoint to connect to.
- /// An optional to observe while waiting for the connection to complete.
- /// A that represents the asynchronous operation. The result is if the connection was successfully established; otherwise, .
- ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default);
-
- ///
- /// Sends the specified data asynchronously to the connected endpoint.
- ///
- /// This method performs a non-blocking operation to send data. If the operation is canceled via
- /// the , the returned task will not complete successfully. Ensure the connected endpoint
- /// is ready to receive data before calling this method.
- /// The data to send, represented as a read-only memory block of bytes.
- /// An optional cancellation token that can be used to cancel the operation.
- /// A representing the asynchronous operation. The result is if the data was sent successfully; otherwise, .
- ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default);
-
- ///
- /// Asynchronously receives data from a source and writes it into the specified buffer.
- ///
- /// This method does not guarantee that the buffer will be completely filled. The caller should
- /// check the return value to determine the number of bytes received.
- /// The memory buffer where the received data will be stored. Must be large enough to hold the incoming data.
- /// A cancellation token that can be used to cancel the operation. Defaults to if not
- /// provided.
- /// A representing the asynchronous operation. The result is the number of bytes
- /// successfully received and written into the buffer. Returns 0 if the end of the data stream is reached.
- ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default);
-
- ///
- /// Closes the current connection or resource, releasing any associated resources.
- ///
- /// Once the connection or resource is closed, it cannot be reopened. Ensure that all necessary
- /// operations are completed before calling this method. This method is typically used to clean up resources when
- /// they are no longer needed.
- ValueTask CloseAsync();
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/ITcpSocketClient.cs b/src/BootstrapBlazor/Services/TcpSocket/ITcpSocketClient.cs
deleted file mode 100644
index ae965fb1a63..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/ITcpSocketClient.cs
+++ /dev/null
@@ -1,93 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Net;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Represents a TCP socket for network communication.
-///
-public interface ITcpSocketClient : IAsyncDisposable
-{
- ///
- /// Gets a value indicating whether the system is currently connected. Default is false.
- ///
- bool IsConnected { get; }
-
- ///
- /// Gets or sets the configuration options for the socket client.
- ///
- SocketClientOptions Options { get; }
-
- ///
- /// Gets the local network endpoint that the socket is bound to.
- ///
- /// This property provides information about the local endpoint of the socket, which is typically
- /// used to identify the local address and port being used for communication. If the socket is not bound to a
- /// specific local endpoint, this property may return .
- IPEndPoint LocalEndPoint { get; }
-
- ///
- /// Gets or sets the callback function to handle received data.
- ///
- /// The callback function should be designed to handle the received data efficiently and
- /// asynchronously. Ensure that the implementation does not block or perform long-running operations, as this may
- /// impact performance.
- Func, ValueTask>? ReceivedCallBack { get; set; }
-
- ///
- /// Gets or sets the callback function that is invoked when a connection attempt is initiated.
- ///
- Func? OnConnecting { get; set; }
-
- ///
- /// Gets or sets the delegate to be invoked when a connection is successfully established.
- ///
- Func? OnConnected { get; set; }
-
- ///
- /// Establishes an asynchronous connection to the specified endpoint.
- ///
- /// This method attempts to establish a connection to the specified endpoint. If the connection
- /// cannot be established, the method returns rather than throwing an exception.
- /// The representing the remote endpoint to connect to. Cannot be null.
- /// A that can be used to cancel the connection attempt. Defaults to if not provided.
- /// A task that represents the asynchronous operation. The task result is if the connection
- /// is successfully established; otherwise, .
- ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default);
-
- ///
- /// Sends the specified data asynchronously to the target endpoint.
- ///
- /// This method performs a non-blocking operation to send data. If the operation is canceled via
- /// the , the task will complete with a canceled state. Ensure the connection is properly
- /// initialized before calling this method.
- /// The byte array containing the data to be sent. Cannot be null or empty.
- /// An optional to observe while waiting for the operation to complete.
- /// A task that represents the asynchronous operation. The task result is if the data was
- /// sent successfully; otherwise, .
- ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default);
-
- ///
- /// Asynchronously receives a block of data from the underlying source.
- ///
- /// This method is non-blocking and completes when data is available or the operation is
- /// canceled. If the operation is canceled, the returned task will be in a faulted state with a .
- /// A cancellation token that can be used to cancel the operation. The default value is .
- /// A containing a of bytes representing the received data.
- /// The returned memory may be empty if no data is available.
- ValueTask> ReceiveAsync(CancellationToken token = default);
-
- ///
- /// Closes the current connection or resource, releasing any associated resources.
- ///
- /// Once the connection or resource is closed, it cannot be reopened. Ensure that all necessary
- /// operations are completed before calling this method. This method is typically used to clean up resources when
- /// they are no longer needed.
- ValueTask CloseAsync();
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/ITcpSocketFactory.cs b/src/BootstrapBlazor/Services/TcpSocket/ITcpSocketFactory.cs
deleted file mode 100644
index 4384477477c..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/ITcpSocketFactory.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// ITcpSocketFactory Interface
-///
-public interface ITcpSocketFactory : IAsyncDisposable
-{
- ///
- /// Retrieves an existing TCP socket client by name or creates a new one using the specified configuration.
- ///
- /// The unique name of the TCP socket client to retrieve or create. Cannot be null or empty.
- /// A delegate used to configure the for the new TCP socket client if it does not
- /// already exist. This delegate is invoked only when a new client is created.
- /// An instance of corresponding to the specified name. If the client already exists,
- /// the existing instance is returned; otherwise, a new instance is created and returned.
- ITcpSocketClient GetOrCreate(string name, Action valueFactory);
-
- ///
- /// Removes the TCP socket client associated with the specified name.
- ///
- /// The name of the TCP socket client to remove. Cannot be or empty.
- /// The removed instance if a client with the specified name exists; otherwise, .
- ITcpSocketClient? Remove(string name);
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/ISocketDataPropertyConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/ISocketDataPropertyConverter.cs
deleted file mode 100644
index b49b0a2a383..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/ISocketDataPropertyConverter.cs
+++ /dev/null
@@ -1,19 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Socket 数据转换器接口
-///
-public interface ISocketDataPropertyConverter
-{
- ///
- /// 将数据转换为指定类型的对象
- ///
- ///
- ///
- object? Convert(ReadOnlyMemory data);
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataBoolConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataBoolConverter.cs
deleted file mode 100644
index de8d2162e84..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataBoolConverter.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 bool 数据转换器
-///
-public class SocketDataBoolConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- var ret = false;
- if (data.Length == 1)
- {
- ret = data.Span[0] != 0x00;
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataByteArrayConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataByteArrayConverter.cs
deleted file mode 100644
index cea9b606969..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataByteArrayConverter.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 byte[] 数组转换器
-///
-public class SocketDataByteArrayConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- return data.ToArray();
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataDoubleBigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataDoubleBigEndianConverter.cs
deleted file mode 100644
index 2b4559d95a0..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataDoubleBigEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 double 数据大端转换器
-///
-public class SocketDataDoubleBigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- double ret = 0;
- if (data.Length <= 8)
- {
- Span paddedSpan = stackalloc byte[8];
- data.Span.CopyTo(paddedSpan[(8 - data.Length)..]);
- if (BinaryPrimitives.TryReadDoubleBigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataDoubleLittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataDoubleLittleEndianConverter.cs
deleted file mode 100644
index 06c6b27ee9d..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataDoubleLittleEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 double 数据小端转换器
-///
-public class SocketDataDoubleLittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- double ret = 0;
- if (data.Length <= 8)
- {
- Span paddedSpan = stackalloc byte[8];
- data.Span.CopyTo(paddedSpan[(8 - data.Length)..]);
- if (BinaryPrimitives.TryReadDoubleLittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataEnumConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataEnumConverter.cs
deleted file mode 100644
index 80aec33cc4c..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataEnumConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 Enum 数据转换器
-///
-public class SocketDataEnumConverter(Type? type) : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- object? ret = null;
- if (type != null)
- {
- if (data.Length == 1)
- {
- var v = data.Span[0];
- if (Enum.TryParse(type, v.ToString(), out var enumValue))
- {
- ret = enumValue;
- }
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt16BigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt16BigEndianConverter.cs
deleted file mode 100644
index 94fcfeb8bab..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt16BigEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 short 数据大端转换器
-///
-public class SocketDataInt16BigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- short ret = 0;
- if (data.Length <= 2)
- {
- Span paddedSpan = stackalloc byte[2];
- data.Span.CopyTo(paddedSpan[(2 - data.Length)..]);
- if (BinaryPrimitives.TryReadInt16BigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt16LittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt16LittleEndianConverter.cs
deleted file mode 100644
index 41862b54203..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt16LittleEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 short 数据小端转换器
-///
-public class SocketDataInt16LittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- short ret = 0;
- if (data.Length <= 2)
- {
- Span paddedSpan = stackalloc byte[2];
- data.Span.CopyTo(paddedSpan[(2 - data.Length)..]);
- if (BinaryPrimitives.TryReadInt16LittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt32BigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt32BigEndianConverter.cs
deleted file mode 100644
index 2f76f168de4..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt32BigEndianConverter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 int 数据大端转换器
-///
-public class SocketDataInt32BigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- var ret = 0;
- if (data.Length <= 4)
- {
- Span paddedSpan = stackalloc byte[4];
- data.Span.CopyTo(paddedSpan[(4 - data.Length)..]);
-
- if (BinaryPrimitives.TryReadInt32BigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt32LittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt32LittleEndianConverter.cs
deleted file mode 100644
index d833da17183..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt32LittleEndianConverter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 int 数据小端转换器
-///
-public class SocketDataInt32LittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- var ret = 0;
- if (data.Length <= 4)
- {
- Span paddedSpan = stackalloc byte[4];
- data.Span.CopyTo(paddedSpan[(4 - data.Length)..]);
-
- if (BinaryPrimitives.TryReadInt32LittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt64BigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt64BigEndianConverter.cs
deleted file mode 100644
index 5dc2d22f350..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt64BigEndianConverter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 long 数据大端转换器
-///
-public class SocketDataInt64BigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- long ret = 0;
- if (data.Length <= 8)
- {
- Span paddedSpan = stackalloc byte[8];
- data.Span.CopyTo(paddedSpan[(8 - data.Length)..]);
-
- if (BinaryPrimitives.TryReadInt64BigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt64LittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt64LittleEndianConverter.cs
deleted file mode 100644
index dabbda71b7e..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataInt64LittleEndianConverter.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 long 数据小端转换器
-///
-public class SocketDataInt64LittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- long ret = 0;
- if (data.Length <= 8)
- {
- Span paddedSpan = stackalloc byte[8];
- data.Span.CopyTo(paddedSpan[(8 - data.Length)..]);
-
- if (BinaryPrimitives.TryReadInt64LittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataSingleBigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataSingleBigEndianConverter.cs
deleted file mode 100644
index 14753c8a50a..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataSingleBigEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 float 数据大端转换器
-///
-public class SocketDataSingleBigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- float ret = 0;
- if (data.Length <= 4)
- {
- Span paddedSpan = stackalloc byte[4];
- data.Span.CopyTo(paddedSpan[(4 - data.Length)..]);
- if (BinaryPrimitives.TryReadSingleBigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataSingleLittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataSingleLittleEndianConverter.cs
deleted file mode 100644
index 0c3132aa406..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataSingleLittleEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 float 数据小端转换器
-///
-public class SocketDataSingleLittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- float ret = 0;
- if (data.Length <= 4)
- {
- Span paddedSpan = stackalloc byte[4];
- data.Span.CopyTo(paddedSpan[(4 - data.Length)..]);
- if (BinaryPrimitives.TryReadSingleLittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataStringConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataStringConverter.cs
deleted file mode 100644
index 9b87b5577e0..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataStringConverter.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Text;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 string 数据转换器
-///
-public class SocketDataStringConverter(string? encodingName) : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- var encoding = string.IsNullOrEmpty(encodingName) ? Encoding.UTF8 : Encoding.GetEncoding(encodingName);
- return encoding.GetString(data.Span);
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt16BigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt16BigEndianConverter.cs
deleted file mode 100644
index 96aba7ceaf8..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt16BigEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 ushort 数据大端转换器
-///
-public class SocketDataUInt16BigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- ushort ret = 0;
- if (data.Length <= 2)
- {
- Span paddedSpan = stackalloc byte[2];
- data.Span.CopyTo(paddedSpan[(2 - data.Length)..]);
- if (BinaryPrimitives.TryReadUInt16BigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt16LittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt16LittleEndianConverter.cs
deleted file mode 100644
index 4abd0b76cf1..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt16LittleEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 ushort 数据小端转换器
-///
-public class SocketDataUInt16LittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- ushort ret = 0;
- if (data.Length <= 2)
- {
- Span paddedSpan = stackalloc byte[2];
- data.Span.CopyTo(paddedSpan[(2 - data.Length)..]);
- if (BinaryPrimitives.TryReadUInt16LittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt32BigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt32BigEndianConverter.cs
deleted file mode 100644
index eb26d1b5051..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt32BigEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 uint 数据大端转换器
-///
-public class SocketDataUInt32BigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- uint ret = 0;
- if (data.Length <= 4)
- {
- Span paddedSpan = stackalloc byte[4];
- data.Span.CopyTo(paddedSpan[(4 - data.Length)..]);
- if (BinaryPrimitives.TryReadUInt32BigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt32LittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt32LittleEndianConverter.cs
deleted file mode 100644
index 727f339ed6f..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt32LittleEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 uint 数据小端转换器
-///
-public class SocketDataUInt32LittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- uint ret = 0;
- if (data.Length <= 4)
- {
- Span paddedSpan = stackalloc byte[4];
- data.Span.CopyTo(paddedSpan[(4 - data.Length)..]);
- if (BinaryPrimitives.TryReadUInt32LittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt64BigEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt64BigEndianConverter.cs
deleted file mode 100644
index 5e3d6ef9d94..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt64BigEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 ulong 数据大端转换器
-///
-public class SocketDataUInt64BigEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- ulong ret = 0;
- if (data.Length <= 8)
- {
- Span paddedSpan = stackalloc byte[8];
- data.Span.CopyTo(paddedSpan[(8 - data.Length)..]);
- if (BinaryPrimitives.TryReadUInt64BigEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt64LittleEndianConverter.cs b/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt64LittleEndianConverter.cs
deleted file mode 100644
index ee976251e97..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/PropertyConverter/SocketDataUInt64LittleEndianConverter.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Buffers.Binary;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Sokcet 数据转换为 ulong 数据小端转换器
-///
-public class SocketDataUInt64LittleEndianConverter : ISocketDataPropertyConverter
-{
- ///
- ///
- ///
- ///
- public object? Convert(ReadOnlyMemory data)
- {
- ulong ret = 0;
- if (data.Length <= 8)
- {
- Span paddedSpan = stackalloc byte[8];
- data.Span.CopyTo(paddedSpan[(8 - data.Length)..]);
- if (BinaryPrimitives.TryReadUInt64LittleEndian(paddedSpan, out var v))
- {
- ret = v;
- }
- }
- return ret;
- }
-}
diff --git a/src/BootstrapBlazor/Services/TcpSocket/SocketClientOptions.cs b/src/BootstrapBlazor/Services/TcpSocket/SocketClientOptions.cs
deleted file mode 100644
index d6d525c4fbf..00000000000
--- a/src/BootstrapBlazor/Services/TcpSocket/SocketClientOptions.cs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using System.Net;
-
-namespace BootstrapBlazor.Components;
-
-///
-/// Represents configuration options for a socket client, including buffer sizes, timeouts, and endpoints.
-///
-/// Use this class to configure various settings for a socket client, such as connection timeouts,
-/// buffer sizes, and local or remote endpoints. These options allow fine-tuning of socket behavior to suit specific
-/// networking scenarios.
-public class SocketClientOptions
-{
- ///
- /// Gets or sets the size, in bytes, of the receive buffer used by the connection.
- ///
- public int ReceiveBufferSize { get; set; } = 1024 * 64;
-
- ///
- /// Gets or sets a value indicating whether automatic receiving data is enabled. Default is true.
- ///
- public bool IsAutoReceive { get; set; } = true;
-
- ///
- /// Gets or sets the timeout duration, in milliseconds, for establishing a connection.
- ///
- public int ConnectTimeout { get; set; }
-
- ///
- /// Gets or sets the duration, in milliseconds, to wait for a send operation to complete before timing out.
- ///
- /// If the send operation does not complete within the specified timeout period, an exception may
- /// be thrown.
- public int SendTimeout { get; set; }
-
- ///
- /// Gets or sets the amount of time, in milliseconds, that the receiver will wait for a response before timing out.
- ///
- /// Use this property to configure the maximum wait time for receiving a response. Setting an
- /// appropriate timeout can help prevent indefinite blocking in scenarios where responses may be delayed or
- /// unavailable.
- public int ReceiveTimeout { get; set; }
-
- ///
- /// Gets or sets the local endpoint for the socket client. Default value is
- ///
- /// This property specifies the local network endpoint that the socket client will bind to when establishing a connection.
- public IPEndPoint LocalEndPoint { get; set; } = new(IPAddress.Any, 0);
-
- ///
- /// Gets or sets a value indicating whether logging is enabled. Default value is false.
- ///
- public bool EnableLog { get; set; }
-
- ///
- /// Gets or sets a value indicating whether the system should automatically attempt to reconnect after a connection is lost. Default value is false.
- ///
- public bool IsAutoReconnect { get; set; }
-
- ///
- /// Gets or sets the interval, in milliseconds, between reconnection attempts. Default value is 5000.
- ///
- public int ReconnectInterval { get; set; } = 5000;
-}
diff --git a/src/BootstrapBlazor/Utils/Utility.cs b/src/BootstrapBlazor/Utils/Utility.cs
index c2be34a3c4d..3cfdea287a8 100644
--- a/src/BootstrapBlazor/Utils/Utility.cs
+++ b/src/BootstrapBlazor/Utils/Utility.cs
@@ -8,10 +8,7 @@
using System.ComponentModel;
using System.Data;
using System.Linq.Expressions;
-using System.Net;
-using System.Net.Sockets;
using System.Reflection;
-using System.Runtime.Versioning;
namespace BootstrapBlazor.Components;
@@ -901,63 +898,4 @@ static Expression> CreateLambda(Type
///
///
public static IStringLocalizer? CreateLocalizer(Type type) => CacheManager.CreateLocalizerByType(type);
-
- ///
- /// Converts a string representation of an IP address or hostname into an object.
- ///
- /// This method handles common special cases for IP address strings, such as "localhost" and
- /// "any". For other inputs, it attempts to parse the string as an IP address using . If parsing fails, the method resolves the input as a
- /// hostname.
- /// A string containing the IP address or hostname to convert. Special values include:
- /// - "localhost" returns the loopback address ().
- "any" returns the wildcard address
- /// ().
For other values, the method attempts to parse the
- /// string as an IP address or resolve it as a hostname.
- /// An object representing the parsed or resolved IP address. If the input cannot be parsed
- /// or resolved, the method returns a default IP address.
- [UnsupportedOSPlatform("browser")]
- public static IPAddress ConvertToIPAddress(string ipString)
- {
- if (string.IsNullOrEmpty(ipString))
- {
- throw new ArgumentNullException(nameof(ipString), "IP address cannot be null or empty.");
- }
-
- if (ipString.Equals("localhost", StringComparison.OrdinalIgnoreCase))
- {
- return IPAddress.Loopback;
- }
- if (ipString.Equals("any", StringComparison.OrdinalIgnoreCase))
- {
- return IPAddress.Any;
- }
-
- return IPAddress.TryParse(ipString, out var ip) ? ip : IPAddressByHostName;
- }
-
- [ExcludeFromCodeCoverage]
-
- [UnsupportedOSPlatform("browser")]
- private static IPAddress IPAddressByHostName => Dns.GetHostAddresses(Dns.GetHostName(), AddressFamily.InterNetwork).FirstOrDefault() ?? IPAddress.Any;
-
- ///
- /// Converts a string representation of an IP address and a port number into an instance.
- ///
- /// This method is not supported on browser platforms.
- /// The string representation of the IP address. Must be a valid IPv4 or IPv6 address.
- /// The port number associated with the endpoint. Must be between 0 and 65535.
- /// An representing the specified IP address and port.
- /// Thrown if is less than 0 or greater than 65535.
- [UnsupportedOSPlatform("browser")]
- public static IPEndPoint ConvertToIpEndPoint(string ipString, int port)
- {
- if (port < 0 || port > 65535)
- {
- throw new ArgumentOutOfRangeException(nameof(port), "Port must be between 0 and 65535.");
- }
-
- var address = ConvertToIPAddress(ipString);
- return new IPEndPoint(address, port);
- }
}
diff --git a/test/UnitTest/Services/DefaultSocketClientProviderTest.cs b/test/UnitTest/Services/DefaultSocketClientProviderTest.cs
deleted file mode 100644
index 51918355063..00000000000
--- a/test/UnitTest/Services/DefaultSocketClientProviderTest.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.Logging;
-using System.Net;
-using System.Net.Sockets;
-
-namespace UnitTest.Services;
-
-public class DefaultSocketClientProviderTest
-{
- [Fact]
- public async Task DefaultSocketClient_Ok()
- {
- var sc = new ServiceCollection();
- sc.AddBootstrapBlazorTcpSocketFactory();
- var provider = sc.BuildServiceProvider();
- var clientProvider = provider.GetRequiredService();
-
- // 未建立连接时 IsConnected 应为 false
- Assert.False(clientProvider.IsConnected);
-
- // 未建立连接直接调用 ReceiveAsync 方法
- var buffer = new byte[1024];
- var len = await clientProvider.ReceiveAsync(buffer);
- Assert.Equal(0, len);
- }
-
- [Fact]
- public async Task ReceiveAsync_Ok()
- {
- var port = 8100;
- // 测试接收数据时服务器断开未连接的情况
- StartTcpServer(port);
-
- var sc = new ServiceCollection();
- sc.AddBootstrapBlazorTcpSocketFactory();
- var provider = sc.BuildServiceProvider();
- var factory = provider.GetRequiredService();
- var client = factory.GetOrCreate("provider", op =>
- {
- op.LocalEndPoint = Utility.ConvertToIpEndPoint("localhost", 0);
- op.IsAutoReceive = false;
- op.EnableLog = false;
- });
-
- await client.ConnectAsync("127.0.0.1", port);
- Assert.True(client.IsConnected);
-
- var buffer = await client.ReceiveAsync();
- Assert.Equal(2, buffer.Length);
-
- await Task.Delay(50);
- buffer = await client.ReceiveAsync();
- Assert.False(client.IsConnected);
- }
-
- [Fact]
- public void SocketClientOptions_Ok()
- {
- var options = new SocketClientOptions
- {
- ReceiveBufferSize = 1024 * 64,
- IsAutoReceive = true,
- ConnectTimeout = 1000,
- SendTimeout = 500,
- ReceiveTimeout = 500,
- LocalEndPoint = new IPEndPoint(IPAddress.Loopback, 0)
- };
- Assert.Equal(1024 * 64, options.ReceiveBufferSize);
- Assert.True(options.IsAutoReceive);
- Assert.Equal(1000, options.ConnectTimeout);
- Assert.Equal(500, options.SendTimeout);
- Assert.Equal(500, options.ReceiveTimeout);
- Assert.Equal(new IPEndPoint(IPAddress.Loopback, 0), options.LocalEndPoint);
- }
-
- private static TcpListener StartTcpServer(int port)
- {
- var server = new TcpListener(IPAddress.Loopback, port);
- server.Start();
- Task.Run(() => AcceptClientsAsync(server));
- return server;
- }
-
- private static async Task AcceptClientsAsync(TcpListener server)
- {
- while (true)
- {
- var client = await server.AcceptTcpClientAsync();
- _ = Task.Run(async () =>
- {
- using var stream = client.GetStream();
- while (true)
- {
- var buffer = new byte[1024];
-
- // 模拟拆包发送第二段数据
- await stream.WriteAsync(new byte[] { 0x3, 0x4 }, CancellationToken.None);
-
- // 等待 20ms
- await Task.Delay(20);
- client.Close();
- }
- });
- }
- }
-}
diff --git a/test/UnitTest/Services/SocketDataConverterCollectionsTest.cs b/test/UnitTest/Services/SocketDataConverterCollectionsTest.cs
deleted file mode 100644
index db2fe233a09..00000000000
--- a/test/UnitTest/Services/SocketDataConverterCollectionsTest.cs
+++ /dev/null
@@ -1,105 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-
-namespace UnitTest.Services;
-
-public class SocketDataConverterCollectionsTest : BootstrapBlazorTestBase
-{
- protected override void ConfigureConfiguration(IServiceCollection services)
- {
- base.ConfigureConfiguration(services);
-
- services.ConfigureSocketDataConverters(options =>
- {
- options.AddTypeConverter();
- options.AddPropertyConverter(entity => entity.Header, new SocketDataPropertyConverterAttribute()
- {
- Offset = 0,
- Length = 5
- });
- options.AddPropertyConverter(entity => entity.Body, new SocketDataPropertyConverterAttribute()
- {
- Offset = 5,
- Length = 2
- });
-
- // 为提高代码覆盖率 重复添加转换器以后面的为准
- options.AddTypeConverter();
- options.AddPropertyConverter(entity => entity.Header, new SocketDataPropertyConverterAttribute()
- {
- Offset = 0,
- Length = 5
- });
- });
- }
-
- [Fact]
- public void TryGetConverter_Ok()
- {
- var service = Context.Services.GetRequiredService>();
- Assert.NotNull(service.Value);
-
- var ret = service.Value.TryGetTypeConverter(out var converter);
- Assert.True(ret);
- Assert.NotNull(converter);
-
- var fakeConverter = service.Value.TryGetTypeConverter(out var fooConverter);
- Assert.False(fakeConverter);
- Assert.Null(fooConverter);
-
- ret = service.Value.TryGetPropertyConverter(entity => entity.Header, out var propertyConverterAttribute);
- Assert.True(ret);
- Assert.NotNull(propertyConverterAttribute);
- Assert.True(propertyConverterAttribute is { Offset: 0, Length: 5 });
-
- ret = service.Value.TryGetPropertyConverter(entity => entity.Name, out var fooPropertyConverterAttribute);
- Assert.False(ret);
- Assert.Null(fooPropertyConverterAttribute);
-
- ret = service.Value.TryGetPropertyConverter(entity => entity.ToString(), out _);
- Assert.False(ret);
- }
-
- class MockEntity
- {
- public byte[]? Header { get; set; }
-
- public byte[]? Body { get; set; }
- }
-
- class MockLoggerProvider : ILoggerProvider
- {
- public ILogger CreateLogger(string categoryName)
- {
- return new MockLogger();
- }
-
- public void Dispose()
- {
-
- }
- }
-
- class MockLogger : ILogger
- {
- public IDisposable? BeginScope(TState state) where TState : notnull
- {
- return null;
- }
-
- public bool IsEnabled(LogLevel logLevel)
- {
- return true;
- }
-
- public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
- {
-
- }
- }
-}
diff --git a/test/UnitTest/Services/TcpSocketFactoryTest.cs b/test/UnitTest/Services/TcpSocketFactoryTest.cs
deleted file mode 100644
index 443a0820b3c..00000000000
--- a/test/UnitTest/Services/TcpSocketFactoryTest.cs
+++ /dev/null
@@ -1,1284 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-using Microsoft.Extensions.Logging;
-using System.Buffers;
-using System.Net;
-using System.Net.Sockets;
-using System.Reflection;
-using System.Text;
-
-namespace UnitTest.Services;
-
-public class TcpSocketFactoryTest
-{
- [Fact]
- public async Task GetOrCreate_Ok()
- {
- // 测试 GetOrCreate 方法创建的 Client 销毁后继续 GetOrCreate 得到的对象是否可用
- var sc = new ServiceCollection();
- sc.AddLogging(builder =>
- {
- builder.AddProvider(new MockLoggerProvider());
- });
- sc.AddBootstrapBlazorTcpSocketFactory();
- var provider = sc.BuildServiceProvider();
- var factory = provider.GetRequiredService();
- var client1 = factory.GetOrCreate("demo", op => op.LocalEndPoint = Utility.ConvertToIpEndPoint("localhost", 0));
- await client1.CloseAsync();
-
- var client2 = factory.GetOrCreate("demo", op => op.LocalEndPoint = Utility.ConvertToIpEndPoint("localhost", 0));
- Assert.Equal(client1, client2);
-
- var ip = Dns.GetHostAddresses(Dns.GetHostName(), AddressFamily.InterNetwork).FirstOrDefault() ?? IPAddress.Loopback;
- var client3 = factory.GetOrCreate("demo1", op => op.LocalEndPoint = Utility.ConvertToIpEndPoint(ip.ToString(), 0));
-
- // 测试不合格 IP 地址
- var client4 = factory.GetOrCreate("demo2", op => op.LocalEndPoint = Utility.ConvertToIpEndPoint("256.0.0.1", 0));
-
- var client5 = factory.Remove("demo2");
- Assert.Equal(client4, client5);
- Assert.NotNull(client5);
-
- await client5.DisposeAsync();
- await factory.DisposeAsync();
- }
-
- [Fact]
- public async Task ConnectAsync_Timeout()
- {
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient();
- });
- client.Options.ConnectTimeout = 10;
-
- var connect = await client.ConnectAsync("localhost", 9999);
- Assert.False(connect);
- }
-
- [Fact]
- public async Task ConnectAsync_Cancel()
- {
- var client = CreateClient(builder =>
- {
- builder.AddTransient();
- },
- options =>
- {
- options.ConnectTimeout = 500;
- });
-
- // 测试 ConnectAsync 方法连接取消逻辑
- var cst = new CancellationTokenSource();
- cst.Cancel();
- var connect = await client.ConnectAsync("localhost", 9999, cst.Token);
-
- // 由于信号量被取消,所以连接会失败
- Assert.False(connect);
-
- // 测试真正的连接被取消逻辑
- cst = new CancellationTokenSource(200);
- connect = await client.ConnectAsync("localhost", 9999, cst.Token);
- Assert.False(connect);
- }
-
- [Fact]
- public async Task ConnectAsync_Failed()
- {
- var client = CreateClient();
-
- // 测试 ConnectAsync 方法连接失败
- var connect = await client.ConnectAsync("localhost", 9999);
- Assert.False(connect);
- }
-
- [Fact]
- public async Task ConnectAsync_Error()
- {
- var client = CreateClient();
-
- // 反射设置 SocketClientProvider 为空
- var propertyInfo = client.GetType().GetProperty("ServiceProvider", BindingFlags.Public | BindingFlags.Instance);
- Assert.NotNull(propertyInfo);
- propertyInfo.SetValue(client, null);
-
- // 测试 ConnectAsync 方法连接失败
- var ex = await Assert.ThrowsAsync(async () => await client.ConnectAsync("localhost", 9999));
- Assert.NotNull(ex);
-
- // 反射测试 Log 方法
- var methodInfo = client.GetType().GetMethod("Log", BindingFlags.NonPublic | BindingFlags.Instance);
- Assert.NotNull(methodInfo);
- methodInfo.Invoke(client, [LogLevel.Error, null!, "Test error log"]);
- }
-
- [Fact]
- public async Task ConnectAsync_Lock()
- {
- // 测试并发锁问题
- var provider = new MockAutoReconnectLockSocketProvider();
- var client = CreateClient(builder =>
- {
- builder.AddTransient(p => provider);
- });
-
- // 开 5 个线程同时连接
- _ = Task.Run(async () =>
- {
- // 延时 150 保证有一个连接失败
- await Task.Delay(150);
- provider.SetConnected(true);
- });
- var results = await Task.WhenAll(Enumerable.Range(1, 5).Select(i => client.ConnectAsync("localhost", 0).AsTask()));
- // 期望结果是 1个 false 4个 true
- Assert.Equal(1, results.Count(r => !r));
- Assert.Equal(4, results.Count(r => r));
- }
-
- [Fact]
- public async Task Send_Timeout()
- {
- var port = 8887;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient();
- });
- client.Options.SendTimeout = 10;
-
- await client.ConnectAsync("localhost", port);
-
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- var result = await client.SendAsync(data);
- Assert.False(result);
- }
-
- [Fact]
- public async Task SendAsync_Error()
- {
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient();
- });
-
- // 测试未建立连接前调用 SendAsync 方法报异常逻辑
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- var ex = await Assert.ThrowsAsync(async () => await client.SendAsync(data));
- Assert.NotNull(ex);
-
- // 测试发送失败
- var port = 8892;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- await client.ConnectAsync("localhost", port);
- Assert.True(client.IsConnected);
-
- // 内部生成异常日志
- await client.SendAsync(data);
- }
-
- [Fact]
- public async Task SendAsync_Cancel()
- {
- var port = 8881;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- var client = CreateClient();
- Assert.False(client.IsConnected);
-
- // 连接 TCP Server
- await client.ConnectAsync("localhost", port);
- Assert.True(client.IsConnected);
-
- // 测试 SendAsync 方法发送取消逻辑
- var cst = new CancellationTokenSource();
- cst.Cancel();
-
- var result = await client.SendAsync("test", null, cst.Token);
- Assert.False(result);
-
- result = await client.SendAsync("test", Encoding.UTF8, cst.Token);
- Assert.False(result);
-
- // 关闭连接
- StopTcpServer(server);
- }
-
- [Fact]
- public async Task ReceiveAsync_Timeout()
- {
- var port = 8888;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- var client = CreateClient();
- client.Options.ReceiveTimeout = 100;
-
- await client.ConnectAsync("localhost", port);
-
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
- await Task.Delay(220); // 等待接收超时
- }
-
- [Fact]
- public async Task ReceiveAsync_Cancel()
- {
- var port = 8889;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- var client = CreateClient();
- await client.ConnectAsync("localhost", port);
-
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
-
- // 通过反射取消令牌
- var type = client.GetType();
- Assert.NotNull(type);
-
- var fieldInfo = type.GetField("_receiveCancellationTokenSource", BindingFlags.NonPublic | BindingFlags.Instance);
- Assert.NotNull(fieldInfo);
- var tokenSource = fieldInfo.GetValue(client) as CancellationTokenSource;
- Assert.NotNull(tokenSource);
- tokenSource.Cancel();
- await Task.Delay(50);
- }
-
- [Fact]
- public async Task ReceiveAsync_InvalidOperationException()
- {
- // 未连接时调用 ReceiveAsync 方法会抛出 InvalidOperationException 异常
- var client = CreateClient();
- var ex = await Assert.ThrowsAsync(async () => await client.ReceiveAsync());
- Assert.NotNull(ex);
-
- // 已连接但是启用了自动接收功能时调用 ReceiveAsync 方法会抛出 InvalidOperationException 异常
- var port = 8893;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- client.Options.IsAutoReceive = true;
- var connected = await client.ConnectAsync("localhost", port);
- Assert.True(connected);
-
- ex = await Assert.ThrowsAsync(async () => await client.ReceiveAsync());
- Assert.NotNull(ex);
- }
-
- [Fact]
- public async Task ReceiveAsync_Ok()
- {
- var onConnecting = false;
- var onConnected = false;
- var port = 8891;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- var client = CreateClient();
- client.Options.IsAutoReceive = false;
- client.OnConnecting = () =>
- {
- onConnecting = true;
- return Task.CompletedTask;
- };
- client.OnConnected = () =>
- {
- onConnected = true;
- return Task.CompletedTask;
- };
- var connected = await client.ConnectAsync("localhost", port);
- Assert.True(connected);
- Assert.True(onConnecting);
- Assert.True(onConnected);
-
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- var send = await client.SendAsync(data);
- Assert.True(send);
-
- // 未设置数据处理器未开启自动接收时,调用 ReceiveAsync 方法获取数据
- // 需要自己处理粘包分包和业务问题
- var payload = await client.ReceiveAsync();
- Assert.Equal([1, 2, 3, 4, 5], payload.ToArray());
-
- // 由于服务器端模拟了拆包发送第二段数据,所以这里可以再次调用 ReceiveAsync 方法获取第二段数据
- payload = await client.ReceiveAsync();
- Assert.Equal([3, 4], payload.ToArray());
- }
-
- [Fact]
- public async Task ReceiveAsync_Error()
- {
- var client = CreateClient();
-
- // 测试未建立连接前调用 ReceiveAsync 方法报异常逻辑
- var type = client.GetType();
- Assert.NotNull(type);
-
- var methodInfo = type.GetMethod("AutoReceiveAsync", BindingFlags.NonPublic | BindingFlags.Instance);
- Assert.NotNull(methodInfo);
-
- var task = (ValueTask)methodInfo.Invoke(client, null)!;
- var ex = await Assert.ThrowsAsync(async () => await task);
- Assert.NotNull(ex);
-
- var port = 8882;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- Assert.Equal(1024 * 64, client.Options.ReceiveBufferSize);
-
- client.Options.ReceiveBufferSize = 1024 * 20;
- Assert.Equal(1024 * 20, client.Options.ReceiveBufferSize);
-
- ReadOnlyMemory buffer = ReadOnlyMemory.Empty;
- var tcs = new TaskCompletionSource();
-
- // 增加接收回调方法
- client.ReceivedCallBack = b =>
- {
- buffer = b;
- tcs.SetResult();
- return ValueTask.CompletedTask;
- };
-
- await client.ConnectAsync("localhost", port);
-
- // 发送数据导致接收数据异常
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
-
- await tcs.Task;
- Assert.Equal([1, 2, 3, 4, 5], buffer.ToArray());
-
- // 关闭连接
- StopTcpServer(server);
- }
-
- [Fact]
- public async Task AutoReconnect_Ok()
- {
- var client = CreateClient(optionConfigure: options =>
- {
- options.IsAutoReconnect = true;
- options.ReconnectInterval = 200;
- options.IsAutoReceive = true;
- });
-
- // 使用场景自动接收数据,短线后自动重连
- var port = 8894;
- var connect = await client.ConnectAsync("localhost", port);
- Assert.False(connect);
-
- // 开启服务端后,可以自动重连上
- var server = StartTcpServer(port, LoopSendPackageAsync);
- await Task.Delay(250);
- Assert.True(client.IsConnected);
-
- await client.DisposeAsync();
- }
-
- [Fact]
- public async Task AutoReconnect_False()
- {
- var provider = new MockAutoReconnectSocketProvider();
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient(p => provider);
- },
- optionConfigure: options =>
- {
- options.IsAutoReconnect = true;
- options.ReconnectInterval = 200;
- options.IsAutoReceive = true;
- });
-
- // 使用场景自动接收数据,短线后自动重连
- var connect = await client.ConnectAsync("localhost", 0);
- Assert.False(connect);
-
- provider.SetConnected(true);
- await Task.Delay(250);
- Assert.True(client.IsConnected);
- }
-
- [Fact]
- public async Task AutoReconnect_Send_Ok()
- {
- // 发送数据时连接断开了,测试重连功能
- var provider = new MockAutoReconnectSocketProvider();
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient(p => provider);
- }, optionConfigure: options =>
- {
- options.IsAutoReconnect = true;
- options.ReconnectInterval = 200;
- options.IsAutoReceive = true;
- });
-
- provider.SetConnected(true);
- var connect = await client.ConnectAsync("localhost", 0);
- Assert.True(connect);
-
- // 发送时断开连接
- provider.SetSend(false);
- var send = await client.SendAsync("test");
- Assert.False(send);
-
- await Task.Delay(250);
- Assert.True(client.IsConnected);
- }
-
- [Fact]
- public async Task AutoReconnect_Receive_Ok()
- {
- // 接收数据时连接断开了,测试重连功能
- var provider = new MockAutoReconnectSocketProvider();
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient(p => provider);
- }, optionConfigure: options =>
- {
- options.IsAutoReconnect = true;
- options.ReconnectInterval = 200;
- options.IsAutoReceive = false;
- });
-
- provider.SetConnected(true);
- var connect = await client.ConnectAsync("localhost", 0);
- Assert.True(connect);
-
- // 发送时断开连接
- provider.SetReceive(false);
- var buffer = await client.ReceiveAsync();
- Assert.Equal(Memory.Empty, buffer);
-
- await Task.Delay(250);
- provider.SetReceive(true);
- buffer = await client.ReceiveAsync();
- Assert.Equal(5, buffer.Length);
- }
-
- [Fact]
- public async Task AutoReconnect_Cancel()
- {
- // 测试重连时取消逻辑
- var provider = new MockAutoReconnectSocketProvider();
- var client = CreateClient(builder =>
- {
- // 增加发送报错 MockSocket
- builder.AddTransient(p => provider);
- }, optionConfigure: options =>
- {
- options.IsAutoReconnect = true;
- options.ReconnectInterval = 2000;
- options.IsAutoReceive = false;
- });
-
- await client.ConnectAsync("localhost", 0);
- await Task.Delay(100);
- await client.DisposeAsync();
- }
-
- [Fact]
- public async Task FixLengthDataPackageHandler_Ok()
- {
- var port = 8884;
- var server = StartTcpServer(port, MockSplitPackageAsync);
- var client = CreateClient();
- var tcs = new TaskCompletionSource();
- var receivedBuffer = new byte[1024];
-
- // 设置数据适配器
- var adapter = new DataPackageAdapter
- {
- DataPackageHandler = new FixLengthDataPackageHandler(7)
- };
- client.SetDataPackageAdapter(adapter, buffer =>
- {
- // buffer 即是接收到的数据
- buffer.CopyTo(receivedBuffer);
- receivedBuffer = receivedBuffer[..buffer.Length];
- tcs.SetResult();
- return ValueTask.CompletedTask;
- });
-
- // 测试 ConnectAsync 方法
- var connect = await client.ConnectAsync("localhost", port);
- Assert.True(connect);
- Assert.True(client.IsConnected);
-
- // 测试 SendAsync 方法
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- var result = await client.SendAsync(data);
- Assert.True(result);
-
- await tcs.Task;
- Assert.Equal([1, 2, 3, 4, 5, 3, 4], receivedBuffer.ToArray());
-
- // 关闭连接
- await client.CloseAsync();
- StopTcpServer(server);
- }
-
- [Fact]
- public async Task FixLengthDataPackageHandler_Sticky()
- {
- var port = 8885;
- var server = StartTcpServer(port, MockStickyPackageAsync);
- var client = CreateClient();
- var tcs = new TaskCompletionSource();
- var receivedBuffer = new byte[128];
-
- // 连接 TCP Server
- var connect = await client.ConnectAsync("localhost", port);
-
- // 设置数据适配器
- var adapter = new DataPackageAdapter
- {
- DataPackageHandler = new FixLengthDataPackageHandler(7)
- };
-
- client.SetDataPackageAdapter(adapter, buffer =>
- {
- // buffer 即是接收到的数据
- buffer.CopyTo(receivedBuffer);
- receivedBuffer = receivedBuffer[..buffer.Length];
- tcs.SetResult();
- return ValueTask.CompletedTask;
- });
-
- // 发送数据
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
-
- // 等待接收数据处理完成
- await tcs.Task;
-
- // 验证接收到的数据
- Assert.Equal([1, 2, 3, 4, 5, 3, 4], receivedBuffer.ToArray());
-
- // 重置接收缓冲区
- receivedBuffer = new byte[1024];
- tcs = new TaskCompletionSource();
-
- // 等待第二次数据
- await tcs.Task;
-
- // 验证第二次收到的数据
- Assert.Equal([2, 2, 3, 4, 5, 6, 7], receivedBuffer.ToArray());
- tcs = new TaskCompletionSource();
- await tcs.Task;
-
- // 验证第三次收到的数据
- Assert.Equal([3, 2, 3, 4, 5, 6, 7], receivedBuffer.ToArray());
-
- // 关闭连接
- await client.CloseAsync();
- StopTcpServer(server);
- }
-
- [Fact]
- public async Task DelimiterDataPackageHandler_Ok()
- {
- var port = 8883;
- var server = StartTcpServer(port, MockDelimiterPackageAsync);
- var client = CreateClient();
- var tcs = new TaskCompletionSource();
- var receivedBuffer = new byte[128];
-
- // 设置数据适配器
- var adapter = new DataPackageAdapter
- {
- DataPackageHandler = new DelimiterDataPackageHandler([13, 10]),
- };
- client.SetDataPackageAdapter(adapter, buffer =>
- {
- // buffer 即是接收到的数据
- buffer.CopyTo(receivedBuffer);
- receivedBuffer = receivedBuffer[..buffer.Length];
- tcs.SetResult();
- return ValueTask.CompletedTask;
- });
-
- // 连接 TCP Server
- var connect = await client.ConnectAsync("localhost", port);
-
- // 发送数据
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
-
- // 等待接收数据处理完成
- await tcs.Task;
-
- // 验证接收到的数据
- Assert.Equal([1, 2, 3, 4, 5, 13, 10], receivedBuffer.ToArray());
-
- // 等待第二次数据
- receivedBuffer = new byte[1024];
- tcs = new TaskCompletionSource();
- await tcs.Task;
-
- // 验证接收到的数据
- Assert.Equal([5, 6, 13, 10], receivedBuffer.ToArray());
-
- // 关闭连接
- await client.CloseAsync();
- StopTcpServer(server);
-
- var handler = new DelimiterDataPackageHandler("\r\n");
- var ex = Assert.Throws(() => new DelimiterDataPackageHandler(string.Empty));
- Assert.NotNull(ex);
-
- ex = Assert.Throws(() => new DelimiterDataPackageHandler(null!));
- Assert.NotNull(ex);
- }
-
- [Fact]
- public async Task TryConvertTo_Ok()
- {
- var port = 8886;
- var server = StartTcpServer(port, MockEntityPackageAsync);
- var client = CreateClient();
- var tcs = new TaskCompletionSource();
- MockEntity? entity = null;
-
- // 设置数据适配器
- var adapter = new DataPackageAdapter
- {
- DataPackageHandler = new FixLengthDataPackageHandler(29),
- };
- client.SetDataPackageAdapter(adapter, new SocketDataConverter(), t =>
- {
- entity = t;
- tcs.SetResult();
- return Task.CompletedTask;
- });
-
- // 连接 TCP Server
- var connect = await client.ConnectAsync("localhost", port);
-
- // 发送数据
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
- await tcs.Task;
-
- Assert.NotNull(entity);
- Assert.Equal([1, 2, 3, 4, 5], entity.Header);
- Assert.Equal([3, 4], entity.Body);
-
- // string
- Assert.Equal("1", entity.Value1);
-
- // string
- Assert.Equal("1", entity.Value14);
-
- // int
- Assert.Equal(9, entity.Value2);
-
- // long
- Assert.Equal(16, entity.Value3);
-
- // double
- Assert.Equal(3.14, entity.Value4);
-
- // single
- Assert.NotEqual(0, entity.Value5);
-
- // short
- Assert.Equal(0x23, entity.Value6);
-
- // ushort
- Assert.Equal(0x24, entity.Value7);
-
- // uint
- Assert.Equal((uint)0x25, entity.Value8);
-
- // ulong
- Assert.Equal((ulong)0x26, entity.Value9);
-
- // bool
- Assert.True(entity.Value10);
-
- // enum
- Assert.Equal(EnumEducation.Middle, entity.Value11);
-
- // foo
- Assert.NotNull(entity.Value12);
- Assert.Equal(0x29, entity.Value12.Id);
- Assert.Equal("test", entity.Value12.Name);
-
- // no attribute
- Assert.Null(entity.Value13);
-
- // 测试 SocketDataConverter 标签功能
- tcs = new TaskCompletionSource();
- client.SetDataPackageAdapter(adapter, t =>
- {
- entity = t;
- tcs.SetResult();
- return Task.CompletedTask;
- });
- await client.SendAsync(data);
- await tcs.Task;
-
- Assert.NotNull(entity);
- Assert.Equal([1, 2, 3, 4, 5], entity.Header);
-
- // 测试数据适配器直接调用 TryConvertTo 方法转换数据
- var adapter2 = new DataPackageAdapter();
- var result = adapter2.TryConvertTo(data, new SocketDataConverter(), out var t);
- Assert.True(result);
- Assert.NotNull(t);
- Assert.Equal([1, 2, 3, 4, 5], entity.Header);
-
- // 测试 SetDataPackageAdapter 泛型无标签情况
- tcs = new TaskCompletionSource();
- NoConvertEntity? noConvertEntity = null;
- client.SetDataPackageAdapter(adapter, t =>
- {
- noConvertEntity = t;
- tcs.SetResult();
- return Task.CompletedTask;
- });
- await client.SendAsync(data);
- await tcs.Task;
- Assert.Null(noConvertEntity);
-
- var converter = new MockSocketDataConverter();
- result = converter.TryConvertTo(new byte[] { 0x1, 0x2 }, out t);
- Assert.False(result);
-
- server.Stop();
- }
-
- [Fact]
- public async Task TryGetTypeConverter_Ok()
- {
- // 测试服务配置转换器
- var port = 8895;
- var server = StartTcpServer(port, MockSplitPackageAsync);
-
- var client = CreateClient(builder =>
- {
- builder.ConfigureSocketDataConverters(options =>
- {
- options.AddTypeConverter();
- options.AddPropertyConverter(entity => entity.Header, new SocketDataPropertyConverterAttribute()
- {
- Offset = 0,
- Length = 5
- });
- options.AddPropertyConverter(entity => entity.Body, new SocketDataPropertyConverterAttribute()
- {
- Offset = 5,
- Length = 2
- });
- });
- });
- var tcs = new TaskCompletionSource();
- var receivedBuffer = new byte[128];
-
- // 连接 TCP Server
- var connect = await client.ConnectAsync("localhost", port);
-
- // 设置数据适配器
- var adapter = new DataPackageAdapter
- {
- DataPackageHandler = new FixLengthDataPackageHandler(7)
- };
-
- OptionConvertEntity? entity = null;
- client.SetDataPackageAdapter(adapter, data =>
- {
- // buffer 即是接收到的数据
- entity = data;
- tcs.SetResult();
- return Task.CompletedTask;
- });
-
- // 发送数据
- var data = new ReadOnlyMemory([1, 2, 3, 4, 5]);
- await client.SendAsync(data);
-
- // 等待接收数据处理完成
- await tcs.Task;
- Assert.NotNull(entity);
- Assert.Equal([1, 2, 3, 4, 5], entity.Header);
- Assert.Equal([3, 4], entity.Body);
-
- server.Stop();
- }
-
- private static TcpListener StartTcpServer(int port, Func handler)
- {
- var server = new TcpListener(IPAddress.Loopback, port);
- server.Start();
- Task.Run(() => AcceptClientsAsync(server, handler));
- return server;
- }
-
- private static async Task AcceptClientsAsync(TcpListener server, Func handler)
- {
- while (true)
- {
- var client = await server.AcceptTcpClientAsync();
- _ = Task.Run(() => handler(client));
- }
- }
-
- private static async Task MockDelimiterPackageAsync(TcpClient client)
- {
- using var stream = client.GetStream();
- while (true)
- {
- var buffer = new byte[10240];
- var len = await stream.ReadAsync(buffer);
- if (len == 0)
- {
- break;
- }
-
- // 回写数据到客户端
- var block = new ReadOnlyMemory(buffer, 0, len);
- await stream.WriteAsync(block, CancellationToken.None);
-
- await Task.Delay(20);
-
- // 模拟拆包发送第二段数据
- await stream.WriteAsync(new byte[] { 13, 10, 0x5, 0x6, 13, 10 }, CancellationToken.None);
- }
- }
-
- private static async Task MockSplitPackageAsync(TcpClient client)
- {
- using var stream = client.GetStream();
- while (true)
- {
- var buffer = new byte[1024];
- var len = await stream.ReadAsync(buffer);
- if (len == 0)
- {
- break;
- }
-
- // 回写数据到客户端
- var block = new ReadOnlyMemory(buffer, 0, len);
- await stream.WriteAsync(block, CancellationToken.None);
-
- // 模拟延时
- await Task.Delay(50);
-
- // 模拟拆包发送第二段数据
- await stream.WriteAsync(new byte[] { 0x3, 0x4 }, CancellationToken.None);
- }
- }
-
- private static async Task MockEntityPackageAsync(TcpClient client)
- {
- using var stream = client.GetStream();
- while (true)
- {
- var buffer = new byte[1024];
- var len = await stream.ReadAsync(buffer);
- if (len == 0)
- {
- break;
- }
-
- // 回写数据到客户端
- await stream.WriteAsync(new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5, 0x3, 0x4, 0x31, 0x09, 0x10, 0x40, 0x09, 0x1E, 0xB8, 0x51, 0xEB, 0x85, 0x1F, 0x40, 0x49, 0x0F, 0xDB, 0x23, 0x24, 0x25, 0x26, 0x01, 0x01, 0x29 }, CancellationToken.None);
- }
- }
-
- private static async Task MockStickyPackageAsync(TcpClient client)
- {
- using var stream = client.GetStream();
- while (true)
- {
- var buffer = new byte[10240];
- var len = await stream.ReadAsync(buffer);
- if (len == 0)
- {
- break;
- }
-
- // 回写数据到客户端
- var block = new ReadOnlyMemory(buffer, 0, len);
- await stream.WriteAsync(block, CancellationToken.None);
-
- // 模拟延时
- await Task.Delay(10);
-
- // 模拟拆包发送第二段数据
- await stream.WriteAsync(new byte[] { 0x3, 0x4, 0x2, 0x2 }, CancellationToken.None);
-
- // 模拟延时
- await Task.Delay(10);
-
- // 模拟粘包发送后续数据
- await stream.WriteAsync(new byte[] { 0x3, 0x4, 0x5, 0x6, 0x7, 0x3, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x1 }, CancellationToken.None);
- }
- }
-
- private static async Task LoopSendPackageAsync(TcpClient client)
- {
- using var stream = client.GetStream();
- while (true)
- {
- // 模拟发送数据
- var data = new byte[] { 1, 2, 3, 4, 5 };
- await stream.WriteAsync(data, CancellationToken.None);
- // 模拟延时
- await Task.Delay(500);
- }
- }
-
- private static void StopTcpServer(TcpListener server)
- {
- server?.Stop();
- }
-
- private static ITcpSocketClient CreateClient(Action? builder = null, Action? optionConfigure = null)
- {
- var sc = new ServiceCollection();
- sc.AddLogging(builder =>
- {
- builder.AddProvider(new MockLoggerProvider());
- });
- sc.AddBootstrapBlazorTcpSocketFactory();
- builder?.Invoke(sc);
-
- var provider = sc.BuildServiceProvider();
- var factory = provider.GetRequiredService();
- var client = factory.GetOrCreate("test", op =>
- {
- op.LocalEndPoint = Utility.ConvertToIpEndPoint("localhost", 0);
- op.EnableLog = true;
- optionConfigure?.Invoke(op);
- });
- return client;
- }
-
- class MockLoggerProvider : ILoggerProvider
- {
- public ILogger CreateLogger(string categoryName)
- {
- return new MockLogger();
- }
-
- public void Dispose()
- {
-
- }
- }
-
- class MockLogger : ILogger
- {
- public IDisposable? BeginScope(TState state) where TState : notnull
- {
- return null;
- }
-
- public bool IsEnabled(LogLevel logLevel)
- {
- return true;
- }
-
- public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter)
- {
-
- }
- }
-
- class MockSendErrorSocketProvider : ISocketClientProvider
- {
- public bool IsConnected { get; private set; }
-
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
-
- public ValueTask CloseAsync()
- {
- return ValueTask.CompletedTask;
- }
-
- public ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- IsConnected = true;
- return ValueTask.FromResult(true);
- }
-
- public ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- return ValueTask.FromResult(0);
- }
-
- public ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- throw new Exception("Mock send error");
- }
- }
-
- class MockConnectTimeoutSocketProvider : ISocketClientProvider
- {
- public bool IsConnected { get; private set; }
-
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
-
- public ValueTask CloseAsync()
- {
- return ValueTask.CompletedTask;
- }
-
- public async ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- await Task.Delay(1000, token);
- IsConnected = false;
- return false;
- }
-
- public ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- return ValueTask.FromResult(0);
- }
-
- public ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- return ValueTask.FromResult(true);
- }
- }
-
- class MockConnectCancelSocketProvider : ISocketClientProvider
- {
- public bool IsConnected { get; private set; }
-
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
-
- public ValueTask CloseAsync()
- {
- return ValueTask.CompletedTask;
- }
-
- public async ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- await Task.Delay(250, token);
- return false;
- }
-
- public ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- return ValueTask.FromResult(0);
- }
-
- public ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- return ValueTask.FromResult(true);
- }
- }
-
- class MockSendTimeoutSocketProvider : ISocketClientProvider
- {
- public bool IsConnected { get; private set; }
-
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Any, 0);
-
- public ValueTask CloseAsync()
- {
- return ValueTask.CompletedTask;
- }
-
- public ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- IsConnected = true;
- return ValueTask.FromResult(true);
- }
-
- public ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- return ValueTask.FromResult(0);
- }
-
- public async ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- // 模拟超时发送
- await Task.Delay(100, token);
- return false;
- }
- }
-
- class MockAutoReconnectLockSocketProvider : ISocketClientProvider
- {
- public bool IsConnected { get; private set; }
-
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Loopback, 0);
-
- public async ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- await Task.Delay(100, token);
- return IsConnected;
- }
-
- public ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- return ValueTask.FromResult(true);
- }
-
- public ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- byte[] data = [1, 2, 3, 4, 5];
- data.CopyTo(buffer);
- return ValueTask.FromResult(5);
- }
-
- public ValueTask CloseAsync()
- {
- return ValueTask.CompletedTask;
- }
-
- public void SetConnected(bool state)
- {
- IsConnected = state;
- }
- }
-
- class MockAutoReconnectSocketProvider : ISocketClientProvider
- {
- public bool IsConnected { get; private set; }
-
- public IPEndPoint LocalEndPoint { get; set; } = new IPEndPoint(IPAddress.Loopback, 0);
-
- public ValueTask ConnectAsync(IPEndPoint endPoint, CancellationToken token = default)
- {
- return ValueTask.FromResult(IsConnected);
- }
-
- private bool _sendState = true;
- public ValueTask SendAsync(ReadOnlyMemory data, CancellationToken token = default)
- {
- return ValueTask.FromResult(_sendState);
- }
-
- private bool _receiveState = true;
- public ValueTask ReceiveAsync(Memory buffer, CancellationToken token = default)
- {
- if (_receiveState)
- {
- byte[] data = [1, 2, 3, 4, 5];
- data.CopyTo(buffer);
- return ValueTask.FromResult(5);
- }
- else
- {
- return ValueTask.FromResult(0);
- }
- }
-
- public ValueTask CloseAsync()
- {
- return ValueTask.CompletedTask;
- }
-
- public void SetConnected(bool state)
- {
- IsConnected = state;
- }
-
- public void SetSend(bool state)
- {
- _sendState = state;
- }
-
- public void SetReceive(bool state)
- {
- _receiveState = state;
- }
- }
-
- [SocketDataTypeConverter(Type = typeof(SocketDataConverter))]
- class MockEntity
- {
- [SocketDataPropertyConverter(Type = typeof(byte[]), Offset = 0, Length = 5)]
- public byte[]? Header { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(byte[]), Offset = 5, Length = 2)]
- public byte[]? Body { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(string), Offset = 7, Length = 1, EncodingName = "utf-8")]
- public string? Value1 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(int), Offset = 8, Length = 1)]
- public int Value2 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(long), Offset = 9, Length = 1)]
- public long Value3 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(double), Offset = 10, Length = 8)]
- public double Value4 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(float), Offset = 18, Length = 4)]
- public float Value5 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(short), Offset = 22, Length = 1)]
- public short Value6 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(ushort), Offset = 23, Length = 1)]
- public ushort Value7 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(uint), Offset = 24, Length = 1)]
- public uint Value8 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(ulong), Offset = 25, Length = 1)]
- public ulong Value9 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(bool), Offset = 26, Length = 1)]
- public bool Value10 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(EnumEducation), Offset = 27, Length = 1)]
- public EnumEducation Value11 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(Foo), Offset = 28, Length = 1, ConverterType = typeof(FooConverter), ConverterParameters = ["test"])]
- public Foo? Value12 { get; set; }
-
- [SocketDataPropertyConverter(Type = typeof(string), Offset = 7, Length = 1)]
- public string? Value14 { get; set; }
-
- public string? Value13 { get; set; }
- }
-
- class MockSocketDataConverter : SocketDataConverter
- {
- protected override bool Parse(ReadOnlyMemory data, MockEntity entity)
- {
- return false;
- }
- }
-
- class FooConverter(string name) : ISocketDataPropertyConverter
- {
- public object? Convert(ReadOnlyMemory data)
- {
- return new Foo() { Id = data.Span[0], Name = name };
- }
- }
-
- class NoConvertEntity
- {
- public byte[]? Header { get; set; }
-
- public byte[]? Body { get; set; }
- }
-
- class OptionConvertEntity
- {
- public byte[]? Header { get; set; }
-
- public byte[]? Body { get; set; }
- }
-}
diff --git a/test/UnitTest/Services/TcpSocketPropertyConverterTest.cs b/test/UnitTest/Services/TcpSocketPropertyConverterTest.cs
deleted file mode 100644
index 60a63ab4533..00000000000
--- a/test/UnitTest/Services/TcpSocketPropertyConverterTest.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the Apache 2.0 License
-// See the LICENSE file in the project root for more information.
-// Maintainer: Argo Zhang(argo@live.ca) Website: https://www.blazor.zone
-
-namespace UnitTest.Services;
-
-public class TcpSocketPropertyConverterTest
-{
- [Fact]
- public void UInt16Converter_Ok()
- {
- var converter = new SocketDataUInt16LittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xFF, 0x00 });
- Assert.Equal((ushort)0xFF, actual);
- }
-
- [Fact]
- public void Int16Converter_Ok()
- {
- var converter = new SocketDataInt16LittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xFF, 0x00 });
- Assert.Equal((short)0xFF, actual);
- }
-
- [Fact]
- public void UInt32Converter_Ok()
- {
- var converter = new SocketDataUInt32LittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xFF, 0x00, 0x00, 0x00 });
- Assert.Equal((uint)0xFF, actual);
- }
-
- [Fact]
- public void Int32Converter_Ok()
- {
- var converter = new SocketDataInt32LittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xFF, 0x00, 0x00, 0x00 });
- Assert.Equal(0xFF, actual);
- }
-
- [Fact]
- public void UInt64Converter_Ok()
- {
- var converter = new SocketDataUInt64LittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
- Assert.Equal((ulong)0xFF, actual);
- }
-
- [Fact]
- public void Int64Converter_Ok()
- {
- var converter = new SocketDataInt64LittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });
- Assert.Equal((long)0xFF, actual);
- }
-
- [Fact]
- public void SingleConverter_Ok()
- {
- var converter = new SocketDataSingleLittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0xC3, 0xF5, 0x48, 0x40 });
- Assert.Equal((float)3.14, actual);
- }
-
- [Fact]
- public void DoubleConverter_Ok()
- {
- var converter = new SocketDataDoubleLittleEndianConverter();
- var actual = converter.Convert(new byte[] { 0x1F, 0x85, 0xEB, 0x51, 0xB8, 0x1E, 0x09, 0x40 });
- Assert.Equal((double)3.14, actual);
- }
-}
diff --git a/test/UnitTest/Utils/UtilityTest.cs b/test/UnitTest/Utils/UtilityTest.cs
index b90980f7d0c..bfbf3d58ad6 100644
--- a/test/UnitTest/Utils/UtilityTest.cs
+++ b/test/UnitTest/Utils/UtilityTest.cs
@@ -743,27 +743,6 @@ public void FormatIp_Test()
Assert.Equal("192.168.1.###", result);
}
- [Fact]
- public void ConvertToIPAddress_Ok()
- {
- var ex = Assert.Throws(() => Utility.ConvertToIPAddress(""));
- Assert.NotNull(ex);
-
- var address = Utility.ConvertToIPAddress("any");
- Assert.Equal(IPAddress.Any, address);
- }
-
- [Fact]
- public void ConvertToIpEndPoint_Ok()
- {
- var ex = Assert.Throws(() => Utility.ConvertToIpEndPoint("localhost", 88990));
- Assert.NotNull(ex);
-
- ex = null;
- ex = Assert.Throws(() => Utility.ConvertToIpEndPoint("localhost", -1000));
- Assert.NotNull(ex);
- }
-
[AutoGenerateClass(Align = Alignment.Center)]
private class Dog
{