Skip to content

Commit 8b42331

Browse files
committed
refactor: 更新 DefaultTcpSocketClient 实现类
1 parent e97d259 commit 8b42331

1 file changed

Lines changed: 74 additions & 55 deletions

File tree

src/extensions/BootstrapBlazor.TouchSocket/Services/DefaultTcpSocketClient.cs

Lines changed: 74 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ namespace BootstrapBlazor.Components;
1212
class DefaultTcpSocketClient : ITcpSocketClient
1313
{
1414
private TcpClient? _client;
15+
private IDataPackageHandler? _dataPackageHandler;
16+
private CancellationTokenSource? _receiveCancellationTokenSource;
17+
private IPEndPoint? _remoteEndPoint;
1518

1619
public bool IsConnected => _client?.Connected ?? false;
1720

18-
public IPEndPoint LocalEndPoint { get; }
21+
public IPEndPoint LocalEndPoint { get; set; }
1922

23+
[NotNull]
2024
public ILogger<DefaultTcpSocketClient>? Logger { get; set; }
2125

22-
public IDataPackageAdapter? DataPackageAdapter { get; set; }
26+
public int ReceiveBufferSize { get; set; } = 1024 * 10;
2327

2428
public DefaultTcpSocketClient(string host, int port = 0)
2529
{
@@ -28,7 +32,15 @@ public DefaultTcpSocketClient(string host, int port = 0)
2832

2933
private static IPAddress GetIPAddress(string host) => host.Equals("localhost", StringComparison.OrdinalIgnoreCase)
3034
? IPAddress.Loopback
31-
: IPAddress.TryParse(host, out var ip) ? ip : Dns.GetHostAddresses(host).FirstOrDefault() ?? IPAddress.Loopback;
35+
: IPAddress.TryParse(host, out var ip) ? ip : IPAddressByHostName;
36+
37+
[ExcludeFromCodeCoverage]
38+
private static IPAddress IPAddressByHostName => Dns.GetHostAddresses(Dns.GetHostName(), AddressFamily.InterNetwork).FirstOrDefault() ?? IPAddress.Loopback;
39+
40+
public void SetDataHandler(IDataPackageHandler handler)
41+
{
42+
_dataPackageHandler = handler;
43+
}
3244

3345
public Task<bool> ConnectAsync(string host, int port, CancellationToken token = default)
3446
{
@@ -44,18 +56,24 @@ public async Task<bool> ConnectAsync(IPEndPoint endPoint, CancellationToken toke
4456
// 释放资源
4557
Close();
4658

47-
// 创建新的 TouchSocketClient 实例
59+
// 创建新的 TcpClient 实例
4860
_client ??= new TcpClient(LocalEndPoint);
4961
await _client.ConnectAsync(endPoint, token);
62+
63+
// 开始接收数据
64+
_ = Task.Run(ReceiveAsync, token);
65+
66+
LocalEndPoint = (IPEndPoint)_client.Client.LocalEndPoint!;
67+
_remoteEndPoint = endPoint;
5068
ret = true;
5169
}
5270
catch (OperationCanceledException ex)
5371
{
54-
LogWarning(ex, $"TCP Socket connect operation was canceled to {endPoint}");
72+
Logger.LogWarning(ex, "TCP Socket connect operation was canceled from {LocalEndPoint} to {RemoteEndPoint}", LocalEndPoint, endPoint);
5573
}
5674
catch (Exception ex)
5775
{
58-
LogError(ex, $"TCP Socket connection failed to {endPoint}");
76+
Logger.LogError(ex, "TCP Socket connection failed from {LocalEndPoint} to {RemoteEndPoint}", LocalEndPoint, endPoint);
5977
}
6078
return ret;
6179
}
@@ -64,93 +82,94 @@ public async Task<bool> SendAsync(Memory<byte> data, CancellationToken token = d
6482
{
6583
if (_client is not { Connected: true })
6684
{
67-
throw new InvalidOperationException("TCP Socket is not connected.");
85+
throw new InvalidOperationException($"TCP Socket is not connected {LocalEndPoint}");
6886
}
6987

7088
var ret = false;
7189
try
7290
{
91+
if (_dataPackageHandler != null)
92+
{
93+
data = await _dataPackageHandler.SendAsync(data);
94+
}
7395
var stream = _client.GetStream();
7496
await stream.WriteAsync(data, token);
7597
ret = true;
7698
}
7799
catch (OperationCanceledException ex)
78100
{
79-
LogWarning(ex, $"TCP Socket send operation was canceled to {_client.Client.RemoteEndPoint}");
101+
Logger.LogWarning(ex, "TCP Socket send operation was canceled from {LocalEndPoint} to {RemoteEndPoint}", LocalEndPoint, _remoteEndPoint);
80102
}
81103
catch (Exception ex)
82104
{
83-
LogError(ex, $"TCP Socket send failed to {_client.Client.RemoteEndPoint}");
105+
Logger.LogError(ex, "TCP Socket send failed from {LocalEndPoint} to {RemoteEndPoint}", LocalEndPoint, _remoteEndPoint);
84106
}
85107
return ret;
86108
}
87109

88-
public async Task<Memory<byte>> ReceiveAsync(int bufferSize = 1024 * 10, CancellationToken token = default)
110+
private async Task ReceiveAsync()
89111
{
90-
if (_client is not { Connected: true })
91-
{
92-
throw new InvalidOperationException("TCP Socket is not connected.");
93-
}
94-
95-
var block = ArrayPool<byte>.Shared.Rent(bufferSize);
96-
var buffer = new Memory<byte>(block);
97-
try
112+
_receiveCancellationTokenSource ??= new();
113+
while (_receiveCancellationTokenSource is { IsCancellationRequested: false })
98114
{
99-
var stream = _client.GetStream();
100-
var len = await stream.ReadAsync(buffer, token);
101-
if (len == 0)
115+
if (_client is not { Connected: true })
102116
{
103-
LogInformation($"TCP Socket received {len} data from {_client.Client.RemoteEndPoint}");
117+
throw new InvalidOperationException($"TCP Socket is not connected {LocalEndPoint}");
104118
}
105-
else
106-
{
107-
buffer = buffer[..len];
108119

109-
if (DataPackageAdapter != null)
120+
try
121+
{
122+
using var block = MemoryPool<byte>.Shared.Rent(ReceiveBufferSize);
123+
var buffer = block.Memory;
124+
var stream = _client.GetStream();
125+
var len = await stream.ReadAsync(buffer, _receiveCancellationTokenSource.Token);
126+
if (len == 0)
110127
{
111-
buffer = await DataPackageAdapter.ReceiveAsync(buffer);
128+
// 远端主机关闭链路
129+
Logger.LogInformation("TCP Socket {LocalEndPoint} received 0 data closed by {RemoteEndPoint}", LocalEndPoint, _remoteEndPoint);
130+
break;
131+
}
132+
else
133+
{
134+
buffer = buffer[..len];
135+
136+
if (_dataPackageHandler != null)
137+
{
138+
await _dataPackageHandler.ReceiveAsync(buffer);
139+
}
112140
}
113141
}
142+
catch (OperationCanceledException ex)
143+
{
144+
Logger.LogWarning(ex, "TCP Socket receive operation was canceled from {LocalEndPoint} to {RemoteEndPoint}", LocalEndPoint, _remoteEndPoint);
145+
}
146+
catch (Exception ex)
147+
{
148+
Logger.LogError(ex, "TCP Socket receive failed from {LocalEndPoint} to {RemoteEndPoint}", LocalEndPoint, _remoteEndPoint);
149+
}
114150
}
115-
catch (OperationCanceledException ex)
116-
{
117-
LogWarning(ex, $"TCP Socket receive operation was canceled to {_client.Client.RemoteEndPoint}");
118-
}
119-
catch (Exception ex)
120-
{
121-
LogError(ex, $"TCP Socket receive failed to {_client.Client.RemoteEndPoint}");
122-
}
123-
finally
124-
{
125-
ArrayPool<byte>.Shared.Return(block);
126-
}
127-
return buffer;
128151
}
129152

130153
public void Close()
131154
{
132155
Dispose(true);
133156
}
134157

135-
private void LogInformation(string message)
136-
{
137-
Logger?.LogInformation("{message}", message);
138-
}
139-
140-
private void LogWarning(Exception ex, string message)
141-
{
142-
Logger?.LogWarning(ex, "{message}", message);
143-
}
144-
145-
private void LogError(Exception ex, string message)
146-
{
147-
Logger?.LogError(ex, "{message}", message);
148-
}
149-
150158
private void Dispose(bool disposing)
151159
{
152160
if (disposing)
153161
{
162+
_remoteEndPoint = null;
163+
164+
// 取消接收数据的任务
165+
if (_receiveCancellationTokenSource is not null)
166+
{
167+
_receiveCancellationTokenSource.Cancel();
168+
_receiveCancellationTokenSource.Dispose();
169+
_receiveCancellationTokenSource = null;
170+
}
171+
172+
// 释放 TcpClient 资源
154173
if (_client != null)
155174
{
156175
_client.Close();

0 commit comments

Comments
 (0)