如何正确使用 TcpClient ReadTimeout
Posted
技术标签:
【中文标题】如何正确使用 TcpClient ReadTimeout【英文标题】:How to properly use TcpClient ReadTimeout 【发布时间】:2012-06-06 20:47:36 【问题描述】:花了比看起来合理的更多时间来找到这个简单问题的答案后,我想我会把我的结果留在这里,这样其他人就不必跳过我刚刚走的所有圈子和错误的道路。
问题在于,如果您使用 TcpClient ReadTimeout 属性并且您的读取操作实际上超时,Microsoft 决定关闭套接字。这不是预期的,不是可取的,不是我所知道的任何其他套接字实现所完成的,并且除了程序员的懒惰之外,没有任何正当理由应该是这种情况。但这就是微软选择做的事情。
无论如何,我发现的所有解决方法,包括在这个站点上,都有各种方式来进行某种形式的繁忙轮询,有些甚至涉及启动另一个线程来执行简单的读取调用。很抱歉,我的 CPU 有比坐在那里忙投票更好的事情要做,尤其是在许多套接字打开的情况下,所以这对我来说不是一个选择。毕竟,这不是 1990 年代初期,繁忙的投票只是你做事的方式。如今,我们有一种称为操作系统的东西,它可以使用中断非常有效地处理这些类型的事情。
无论如何,在另一个切线搜索中,我偶然发现了这篇旧博客文章:
http://blogs.msdn.com/b/mflasko/archive/2006/02/20/535655.aspx
MSDN 博客 > Mike Flasko 的博客 > 读取网络数据时处理超时
告诉您如何正确处理读取超时的解决方案的关键要点是:
此时,人们可能会想捕获异常,然后在同一个 NetworkStream 上重新发出读取。此策略可能导致意外错误。最好的办法是现在将 NetworkStream(套接字)视为处于不稳定状态。这是因为当底层堆栈超时时,底层 I/O 读取被取消。如果数据同时进来,数据会丢失,导致数据流损坏。
以及解决方案:
更好的方法是捕获异常,关闭套接字或 TCPClient 并在必要时重新连接。
虽然我仍然认为这会给 API 的用户带来不必要的负担,但至少它是我在试图找出半正确的数十个网站中能够找到的最合适的解决方案套接字读取超时。
我希望这个问题/评论可以节省我寻找的时间。
【问题讨论】:
我最近也一直在处理那些东西,如果我将超时设置为 1000 毫秒并捕获异常,有时我可能最终会延迟一些程序,因为很难确定传输是否真的或者你遇到了网络问题。例如,我有一部分代码通过网络传输 PNG 图像,代码类似于 while (true) try Receive data and put into a 4096 byte buffer break on exception;然后如果没有可用数据,则中断;如果我不让 1ms 线程休眠,(我知道这很糟糕)数据可用将很快返回 false,并且图像会被撕掉。 这是一个问题吗?即使您回答自己的问题,我觉得如果它是问答形式会好得多。 标题就是问题。我当然可以提出这个问题并在单独的回复中回答,但我是这样做的。这是我要问的原始问题,但在按下发布按钮之前,我认为我应该做足够的研究,以便我可以问一个更“知情”的问题。然而,我没有意识到这个小小的努力最终会花费多少时间。在这个过程中,我回答了我自己的问题。由于花了很长时间才提出一个可以接受的解决方案,我认为让其他人不必重复我必须做的所有时间的研究会很好。 ...另一种选择是根本不问这个问题。但我认为这对其他人会有所帮助。 @Dunk 感谢您的问答帖子,我现在正在努力解决这个问题。我使用 ReadTimeout 属性编写了我的 TCP 服务器客户端应用程序,捕获异常并在同一个 NetStream 上重新发出读取。有趣的是,它适用于 Win 7,但不适用于 Win XP。在 Win XP 上收到 ReadTimeout 的 IOException 后,socket 将被关闭。 【参考方案1】:您正在寻找的是 Poll 或 Select 方法,这些方法允许您在不关闭底层连接的情况下等待超时数据:
http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.poll%28v=vs.110%29.aspx http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.select%28v=vs.110%29.aspx
【讨论】:
以上是关于如何正确使用 TcpClient ReadTimeout的主要内容,如果未能解决你的问题,请参考以下文章