我目前正在编写与使用 TCP/IP 的设备交互的代码。 15 秒不活动后,设备将发送 FIN 数据包以断开连接。我正在使用 Polly 进行重试,确保处理 TcpClient 对象,实例化一个新实例,然后在再次重试 IO 操作之前重新连接到 IP/端口。
在这种情况下,我试图从连接的套接字读取响应。重试策略有效,我得到了响应,但我注意到当它确实必须重试时(由于
ConnectionAborted
套接字异常),大约需要 15 秒才能完成将字节读入缓冲区。我没有做过很多网络编程,所以我在这方面比较无知,我不知道为什么要花这么长时间。
// Retry policy and the TcpClient are private member variables in this case
_readRetryPolicy = Policy.Handle<IOException>()
.RetryAsync(3, onRetryAsync: async (_, _) =>
{
Disconnect();
await ConnectAsync(_ip!, _port).ConfigureAwait(false);
});
public async Task<byte[]> ReadResponseAsync()
{
if (_tcpClient is not TcpClient { Connected: true })
{
Disconnect();
await ConnectAsync(_ip!, _port).ConfigureAwait(false);
// Possible StackOverflowException but I'm just hacking at this problem right now
return await ReadResponseAsync().ConfigureAwait(false);
}
var buffer = new byte[32];
var responseBytesStream = Enumerable.Empty<byte>();
int numBytesRead = 0;
do
{
numBytesRead = await _readRetryPolicy.ExecuteAsync(() => _tcpClient.GetStream().ReadAsync(buffer).AsTask()).ConfigureAwait(false);
responseBytesStream = responseBytesStream.Concat(buffer);
}
while (_tcpClient.GetStream().DataAvailable);
return responseBytesStream.ToArray();
}
public void Disconnect()
{
if (_tcpClient is TcpClient c) c.Dispose();
_tcpClient = null;
}