-
-
Notifications
You must be signed in to change notification settings - Fork 363
doc(ITcpSocketClient): add DataHandler sample code #6331
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
df88564
doc: 增加接收数据示例文档说明
ArgoZhang b56174b
refactor: 重构代码
ArgoZhang ad932d8
doc: 更新配置类说明
ArgoZhang 219008b
doc: 增加数据适配器文档
ArgoZhang 6cbad20
refactor: 更新接收数据示例代码
ArgoZhang b17c4c6
doc: 增加数据适配器菜单
ArgoZhang 3c17b32
doc: 更新示例
ArgoZhang f9c42cf
doc: 增加后台服务
ArgoZhang File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
src/BootstrapBlazor.Server/Components/Samples/Sockets/Adapters.razor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| @page "/socket/adapter" | ||
| @inject IStringLocalizer<Adapters> Localizer | ||
|
|
||
| <h3>@Localizer["AdaptersTitle"]</h3> | ||
| <h4>@Localizer["AdaptersDescription"]</h4> | ||
|
|
||
| <Notice></Notice> | ||
|
|
||
| <DemoBlock Title="@Localizer["NormalTitle"]" | ||
| Introduction="@Localizer["NormalIntro"]" | ||
| Name="Normal" ShowCode="false"> | ||
| <p>本例中连接一个模拟自定义协议服务,每次接收到客户端发来的特定数据后,返回业务数据。这类应用在我们实际应用中非常常见</p> | ||
| <p>通过 <code>SocketClientOptions</code> 配置类关闭自动接收数据功能 <code>IsAutoReceive="false"</code></p> | ||
| <Pre>_client = TcpSocketFactory.GetOrCreate("demo-adapter", options => | ||
| { | ||
| options.IsAutoReceive = false; | ||
| options.LocalEndPoint = new IPEndPoint(IPAddress.Loopback, 0); | ||
| });</Pre> | ||
| <ul class="ul-demo"> | ||
| <li>点击 <b>连接</b> 按钮后通过 <code>ITcpSocketFactory</code> 服务实例创建的 <code>ITcpSocketClient</code> 对象连接到网站模拟 <code>TcpServer</code></li> | ||
| <li>点击 <b>断开</b> 按钮调用 <code>CloseAsync</code> 方法断开 Socket 连接</li> | ||
| <li>点击 <b>发送</b> 按钮调用 <code>SendAsync</code> 方法发送请求数据</li> | ||
| </ul> | ||
| <p class="code-label">通讯协议讲解:</p> | ||
| <p>在实际应用开发中,通讯数据协议很多时候是双方约定的。我们假设本示例通讯协议规约为定长格式具体如下:</p> | ||
| <ul class="ul-demo"> | ||
| <li>发送数据包格式为 <code>请求头(Header)+ 请求体(Body)</code> 长度总和为 12 个字节</li> | ||
| <li>请求头为 4 字节定长,请求体为 8 个字节定长</li> | ||
| <li>请求体为字符串类型数据</li> | ||
| <li>返回数据包格式为 <code>响应头(Header)+ 响应体(Body)</code> 长度总和为 12 个字节</li> | ||
| <li>响应头为 4 字节定长,响应体为 8 个字节定长</li> | ||
| <li>响应体为字符串类型数据</li> | ||
| </ul> | ||
|
|
||
| <div class="row form-inline g-3"> | ||
| <div class="col-12 col-sm-6"> | ||
| <Button Text="连接" Icon="fa-solid fa-play" | ||
| OnClick="OnConnectAsync" IsDisabled="@_client.IsConnected"></Button> | ||
| <Button Text="断开" Icon="fa-solid fa-stop" class="ms-2" | ||
| OnClick="OnCloseAsync" IsDisabled="@(!_client.IsConnected)"></Button> | ||
| <Button Text="发送" Icon="fa-solid fa-paper-plane" class="ms-2" IsAsync="true" | ||
| OnClick="OnSendAsync" IsDisabled="@(!_client.IsConnected)"></Button> | ||
| </div> | ||
| <div class="col-12"> | ||
| <Console Items="@_items" Height="496" HeaderText="模拟通讯示例" | ||
| ShowAutoScroll="true" OnClear="@OnClear"></Console> | ||
| </div> | ||
| </div> | ||
| </DemoBlock> |
136 changes: 136 additions & 0 deletions
136
src/BootstrapBlazor.Server/Components/Samples/Sockets/Adapters.razor.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,136 @@ | ||
| // 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([email protected]) Website: https://www.blazor.zone | ||
|
|
||
| using BootstrapBlazor.Server.Components.Components; | ||
| using System.Net; | ||
| using System.Text; | ||
|
|
||
| namespace BootstrapBlazor.Server.Components.Samples.Sockets; | ||
|
|
||
| /// <summary> | ||
| /// 数据适配器示例 | ||
| /// </summary> | ||
| public partial class Adapters : IDisposable | ||
| { | ||
| [Inject, NotNull] | ||
| private ITcpSocketFactory? TcpSocketFactory { get; set; } | ||
|
|
||
| private ITcpSocketClient _client = null!; | ||
|
|
||
| private List<ConsoleMessageItem> _items = []; | ||
|
|
||
| private readonly IPEndPoint _serverEndPoint = new(IPAddress.Loopback, 8900); | ||
|
|
||
| private readonly CancellationTokenSource _connectTokenSource = new(); | ||
| private readonly CancellationTokenSource _sendTokenSource = new(); | ||
| private readonly CancellationTokenSource _receiveTokenSource = new(); | ||
|
|
||
| /// <summary> | ||
| /// <inheritdoc/> | ||
| /// </summary> | ||
| protected override void OnInitialized() | ||
| { | ||
| base.OnInitialized(); | ||
|
|
||
| // 从服务中获取 ITcpSocketClient 实例 | ||
| _client = TcpSocketFactory.GetOrCreate("demo-adapter", options => | ||
| { | ||
| // 关闭自动接收功能 | ||
| options.IsAutoReceive = false; | ||
| // 设置本地使用的 IP地址与端口 | ||
| options.LocalEndPoint = new IPEndPoint(IPAddress.Loopback, 0); | ||
| }); | ||
| } | ||
|
|
||
| private async Task OnConnectAsync() | ||
| { | ||
| if (_client is { IsConnected: false }) | ||
| { | ||
| await _client.ConnectAsync(_serverEndPoint, _connectTokenSource.Token); | ||
| var state = _client.IsConnected ? "成功" : "失败"; | ||
| _items.Add(new ConsoleMessageItem() | ||
| { | ||
| Message = $"{DateTime.Now}: 连接 {_client.LocalEndPoint} - {_serverEndPoint} {state}", | ||
| Color = _client.IsConnected ? Color.Success : Color.Danger | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| private async Task OnSendAsync() | ||
| { | ||
| if (_client is { IsConnected: true }) | ||
| { | ||
| // 准备通讯数据 | ||
| var data = new byte[12]; | ||
| "2025"u8.CopyTo(data); | ||
| Encoding.UTF8.GetBytes(DateTime.Now.ToString("ddHHmmss")).CopyTo(data, 4); | ||
| var result = await _client.SendAsync(data, _sendTokenSource.Token); | ||
| if (result) | ||
| { | ||
| // 发送成功 | ||
| var payload = await _client.ReceiveAsync(_receiveTokenSource.Token); | ||
| if (!payload.IsEmpty) | ||
| { | ||
| // 解析接收到的数据 | ||
| // 响应头: 4 字节表示响应体长度 [0x32, 0x30, 0x32, 0x35] | ||
| // 响应体: 8 字节当前时间戳字符串 | ||
| data = payload.ToArray(); | ||
| var body = BitConverter.ToString(data); | ||
| _items.Add(new ConsoleMessageItem() | ||
| { | ||
| Message = $"{DateTime.Now}: 接收到来自 {_serverEndPoint} 数据: {Encoding.UTF8.GetString(data)} HEX: {body}" | ||
| }); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private async Task OnCloseAsync() | ||
| { | ||
| if (_client is { IsConnected: true }) | ||
| { | ||
| await _client.CloseAsync(); | ||
| var state = _client.IsConnected ? "失败" : "成功"; | ||
| _items.Add(new ConsoleMessageItem() | ||
| { | ||
| Message = $"{DateTime.Now}: 关闭 {_client.LocalEndPoint} - {_serverEndPoint} {state}", | ||
| Color = _client.IsConnected ? Color.Danger : Color.Success | ||
| }); | ||
| } | ||
| } | ||
|
|
||
| private Task OnClear() | ||
| { | ||
| _items = []; | ||
| return Task.CompletedTask; | ||
| } | ||
|
|
||
| private void Dispose(bool disposing) | ||
| { | ||
| if (disposing) | ||
| { | ||
| // 释放连接令牌资源 | ||
| _connectTokenSource.Cancel(); | ||
| _connectTokenSource.Dispose(); | ||
|
|
||
| // 释放发送令牌资源 | ||
| _sendTokenSource.Cancel(); | ||
| _sendTokenSource.Dispose(); | ||
|
|
||
| // 释放接收令牌资源 | ||
| _receiveTokenSource.Cancel(); | ||
| _receiveTokenSource.Dispose(); | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// <inheritdoc/> | ||
| /// </summary> | ||
| public void Dispose() | ||
| { | ||
| Dispose(true); | ||
| GC.SuppressFinalize(this); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue (complexity): Consider consolidating cancellation logic and extracting repeated code into helpers to simplify and clarify the component.
These steps consolidate your cancellation logic, remove inline buffer manipulation/UI repetition, and keep the socket behavior unchanged.