@@ -12,14 +12,18 @@ namespace BootstrapBlazor.Components;
1212class 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