TcpClient SocketException,无论如何都会在20秒后超时

本文关键字:20秒 超时 SocketException 无论如何 TcpClient | 更新日期: 2023-09-27 17:59:26

我想等待客户端的缓慢响应TcpClient但无论我如何配置它,大约 20 秒后都会超时。这是我的尝试:

using (var client = new TcpClient { ReceiveTimeout = 9999999, SendTimeout = 9999999 })
{
    await client.ConnectAsync(ip, port);
    using (var stream = client.GetStream())
    {
        // Some quick read/writes happen here via the stream with stream.Write() and stream.Read(), successfully.
        // Now the remote host is calculating something long and will reply if finished. This throws the below exception however instead of waiting for >20s.
        var bytesRead = await stream.ReadAsync(new byte[8], 0, 8);
    }
}

例外情况是IOException

无法从传输连接读取数据:连接 尝试失败,因为连接的一方未正确响应 一段时间后,或建立的连接失败,因为 连接的主机无法响应。

。其中包含一个SocketException

连接尝试失败,因为连接的一方没有 一段时间后正确响应或建立连接 失败,因为连接的主机无法响应

SocketErrorCodeTimedOut.

20 年代似乎是 Windows 上的操作系统默认值,但是否可以通过与托管代码交互来覆盖它TcpClient?否则我该如何等待响应?

我也尝试了旧式BeginRead - EndRead方式,同样的事情发生在EndRead上。该问题也不是由Windows防火墙或Defender引起的。

TcpClient SocketException,无论如何都会在20秒后超时

我想等待客户的缓慢响应

请务必注意,是连接失败。连接超时仅用于建立连接,这应该始终非常快。事实上,操作系统将代表应用程序接受连接,因此您实际上只是在谈论数据包往返。21秒应该足够了。

建立连接后,您只需删除ReceiveTimeout/SendTimeout并使用异步读取即可永久等待。

事实证明,远程主机没有及时响应,因此出现了问题。让我详细说明一下,虽然这将是一个非常特定于我的情况的解决方案,但也许它对其他人也很有用。

真正的问题不是超时本身,正如异常所示,而是在后续Read()调用中引发的异常显示:"远程主机强行关闭了现有连接">

远程主机没有故意关闭连接。相反,发生的事情是,当响应缓慢时,它实际上非常繁忙,以至于它也没有处理任何TCP流量。虽然本地主机在等待响应时没有显式发送任何内容,但这仍然是一个问题:本地主机尝试为远程主机的先前传输发送 ACK。由于无法传送这些连接,本地主机确定远程主机"强制关闭"连接。

我从Wireshark的交通中得到了线索(总是很好的尝试查看表面之下的东西而不是猜测(:很明显,当远程主机忙碌时,它表现出完全的无线电静默。同时,Wireshark显示了本地主机进行的重传尝试,表明这是问题背后的原因。

因此,该

解决方案也无法在本地主机上实现,需要更改远程主机的行为。