无论什么

时间:2016-08-01 14:26:07

标签: c# .net sockets tcpclient networkstream

我想等待来自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世纪seems to be an OS default on Windows但是,是否可以通过与TcpClient进行交互来从托管代码覆盖它?或者我怎么能等待响应呢?

我也尝试过旧式BeginRead - EndRead方式,EndRead也是如此。该问题也不是由Windows防火墙或Defender引起的。

2 个答案:

答案 0 :(得分:1)

  

我想等待客户的响应缓慢

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

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

答案 1 :(得分:0)

事实证明,远程主机没有及时响应,因此问题。让我详细说明,虽然这将是一个非常具体的解决方案,但也许对其他人也有用。

真正的问题不是超时本身,正如异常所示,而是后续Read()次调用中抛出的异常显示:“现有连接被远程主机强行关闭”

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

我从Wireshark查看流量时得到了线索(总是很好地试着看看表面下面的东西而不是猜测):很明显,当远程主机忙碌时它显示完整的无线电安静。同时,Wireshark展示了当地主持人进行的重传尝试,表明这是问题的背后。

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