【问题标题】:Knowing when to stop reading from .NET socket on HTTP level知道何时停止从 HTTP 级别的 .NET 套接字读取
【发布时间】:2011-02-24 19:02:36
【问题描述】:

.NET Socket 和 NetworkStream 都提供 Read 方法,当没有可用数据时,该方法会阻塞。问题是,如果客户端不知道消息的大小,则无法可靠地了解服务器何时完成发送消息。

我的问题是 - 更高级别的库(如 HTTP 级别的 WebRequest)使用什么原则来停止从套接字读取并向客户端呈现完整消息,而不诉诸任何类型的读取超时?似乎 HTTP 协议不提供任何“EOF”令牌...

【问题讨论】:

    标签: .net sockets


    【解决方案1】:

    HTTP 1.1 通过使用两种机制之一来管理这一点。在标头中发送content-length,或者使用chunked transfer encoding。分块传输编码是 HTTP 1.1 相对于 HTTP 1.0 的一大优势,在没有发送内容长度的情况下,无法可靠地检测到传输结束,从而导致传输问题与有效负载的实际结束之间存在歧义.在某些情况下(例如 HTTP 上的音频流),没有可能指示传输结束的内容长度或其他编码,但在这种情况下,它对客户端来说并不重要。

    【讨论】:

    • 非常感谢,正是我需要的!
    【解决方案2】:

    有一些方法可以检查套接字是否有待处理的数据。一种是简单检查每个socket的Pending属性,只有有数据才调用Receive。但是,这根本不能很好地扩展,我只建议在具有单个连接的应用程序中使用它。

    Socket.Select 函数可以获取一个 IList of Sockets,并在短时间内将这个列表缩减为仅包含有待处理数据的套接字。然后,您可以安全地调用接收它们而不会阻塞。

    另一种首选方法是使用异步套接字 API。 (在 NetworkStream 上致电 BeginReceiveBeginRead)。在这些情况下,调用不会阻塞,您可以在调用后继续执行代码。您将函数作为参数传递,当数据在套接字上挂起时执行。这是在 .NET 线程池中的后台线程中处理的,因此这里涉及到并发问题,与前两种方法不同。异步工作在 OS 中的较低级别完成,通过使用中断来告诉 CPU 数据何时在网络上等待,而不是像 Select 那样反复轮询数据。

    【讨论】:

    • Socket.Select 不在 Windows 中使用 select 调用? :( 也就是说,除非它是一个非常愚蠢的实现,否则它不应该“反复轮询”(它在我所知道的任何其他语言/库中都没有这样做)。
    • 我不知道select是如何实现的,但我的意思是,用户需要通过调用select来保持轮询,而在异步方法中,他们不需要轮询,但只会在数据未决时被中断。
    • select 如果被 [fast] 轮询,则没有正确使用——想法是 wait 处理可用于读/写/oob 的句柄(并且调用将阻塞直到该时间或 [可选] 超时发生或以其他方式中断)。不过,自行设置很棘手,我同意Begin/End 的建议。
    【解决方案3】:

    在 HTTP 中,content-length HTTP 标头定义了何时可以关闭套接字。

    在 TCP 中,这是任意的,通常客户端或服务器会发送一条特殊消息来通知连接正在终止。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-13
      • 1970-01-01
      • 2017-01-17
      • 2011-05-07
      • 1970-01-01
      • 2021-11-08
      • 2016-02-12
      • 2010-11-09
      相关资源
      最近更新 更多