diff --git a/src/BootstrapBlazor.Server/Components/Samples/SocketFactories.razor b/src/BootstrapBlazor.Server/Components/Samples/SocketFactories.razor
index a528bf0b34d..3617e53e5a1 100644
--- a/src/BootstrapBlazor.Server/Components/Samples/SocketFactories.razor
+++ b/src/BootstrapBlazor.Server/Components/Samples/SocketFactories.razor
@@ -6,13 +6,15 @@
1. 服务注入
-[Inject]
-[NotNull]
-private ITcpSocketFactory? TcpSocketFactory { get; set; }
+services.AddBootstrapBlazorTcpSocketFactory();
2. 使用服务
调用 TcpSocketFactory 实例方法 GetOrCreate 即可得到一个 ITcpSocketClient 实例。内部提供复用机制,调用两次得到的 ITcpSocketClient 为同一对象
+[Inject]
+[NotNull]
+private ITcpSocketFactory? TcpSocketFactory { get; set; }
+
var client = factory.GetOrCreate("192.168.1.100", 0);
3. 使用方法
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Sockets/Notice.razor b/src/BootstrapBlazor.Server/Components/Samples/Sockets/Notice.razor
new file mode 100644
index 00000000000..b618855b426
--- /dev/null
+++ b/src/BootstrapBlazor.Server/Components/Samples/Sockets/Notice.razor
@@ -0,0 +1,3 @@
+
+ ITcpSocketFactory 服务仅在 Server 模式下可用
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Sockets/Receives.razor b/src/BootstrapBlazor.Server/Components/Samples/Sockets/Receives.razor
new file mode 100644
index 00000000000..f62065ad5cd
--- /dev/null
+++ b/src/BootstrapBlazor.Server/Components/Samples/Sockets/Receives.razor
@@ -0,0 +1,44 @@
+@page "/socket/receive"
+@inject IStringLocalizer Localizer
+
+@Localizer["ReceivesTitle"]
+@Localizer["ReceivesDescription"]
+
+
+
+
+ 本例中连接一个模拟时间同步服务,每间隔 10s 自动发送服务器时间戳,连接后无需发送任何数据即可持续收到时间戳数据
+
+ - 点击 连接 按钮后通过
ITcpSocketFactory 服务实例创建的 ITcpSocketClient 对象连接到网站模拟 TcpServer
+ - 点击 断开 按钮调用
CloseAsync 方法断开 Socket 连接
+
+ 使用 ReceivedCallBack 委托获得接收到的数据,可通过 += 方法支持多个客户端接收数据
+ _client.ReceivedCallBack += OnReceivedAsync;
+ 特别注意页面需要继承 IDisposable 或者 IAsyncDisposable 接口,在 Dispose 或者 DisposeAsync 中移除委托
+ private void Dispose(bool disposing)
+{
+ if (disposing)
+ {
+ if (_client is { IsConnected: true })
+ {
+ _client.ReceivedCallBack -= OnReceivedAsync;
+ }
+ }
+}
+
+
+
+
diff --git a/src/BootstrapBlazor.Server/Components/Samples/Sockets/Receives.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Sockets/Receives.razor.cs
new file mode 100644
index 00000000000..e20876a0077
--- /dev/null
+++ b/src/BootstrapBlazor.Server/Components/Samples/Sockets/Receives.razor.cs
@@ -0,0 +1,92 @@
+// 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.Server.Components.Samples.Sockets;
+
+///
+///
+///
+public partial class Receives : ComponentBase, IDisposable
+{
+ [Inject, NotNull]
+ private ITcpSocketFactory? TcpSocketFactory { get; set; }
+
+ private ITcpSocketClient _client = null!;
+
+ private List _items = [];
+
+ ///
+ ///
+ ///
+ protected override void OnInitialized()
+ {
+ base.OnInitialized();
+
+ // 从服务中获取 Socket 实例
+ _client = TcpSocketFactory.GetOrCreate("bb", key => new IPEndPoint(IPAddress.Loopback, 0));
+ _client.ReceivedCallBack += OnReceivedAsync;
+ }
+
+ private async Task OnConnectAsync()
+ {
+ if (_client is { IsConnected: false })
+ {
+ await _client.ConnectAsync("127.0.0.1", 8800, CancellationToken.None);
+ }
+ }
+
+ private async Task OnCloseAsync()
+ {
+ if (_client is { IsConnected: true })
+ {
+ await _client.CloseAsync();
+ }
+ }
+
+ private Task OnClear()
+ {
+ _items = [];
+ return Task.CompletedTask;
+ }
+
+ private async ValueTask OnReceivedAsync(ReadOnlyMemory data)
+ {
+ // 将数据显示为十六进制字符串
+ var payload = System.Text.Encoding.UTF8.GetString(data.Span);
+ _items.Add(new ConsoleMessageItem
+ {
+ Message = $"接收到来自站点的数据为 {payload}"
+ });
+
+ // 保持队列中最大数量为 50
+ if (_items.Count > 50)
+ {
+ _items.RemoveAt(0);
+ }
+ await InvokeAsync(StateHasChanged);
+ }
+
+ private void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_client is { IsConnected: true })
+ {
+ _client.ReceivedCallBack -= OnReceivedAsync;
+ }
+ }
+ }
+
+ ///
+ ///
+ ///
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+}
diff --git a/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs b/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs
index a90ea8df21e..3f0dcc34693 100644
--- a/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs
+++ b/src/BootstrapBlazor.Server/Extensions/MenusLocalizerExtensions.cs
@@ -91,6 +91,13 @@ public static List