【问题标题】:Letting the client pull data让客户端拉取数据
【发布时间】:2009-07-10 22:05:10
【问题描述】:

我正在用 C# 编写一个服务器,它创建一个(很长,甚至可能是无限的)IEnumerable<Result> 以响应客户端请求,然后将这些结果流式传输回客户端。

我可以这样设置吗它可以拉下几个Results,将它们序列化,然后将它们填充到网络上?

NetworkStream.BeginWrite 是这样工作的吗?文档不清楚(对我而言)何时调用回调方法。它是否基本上立即发生,只是在另一个线程上阻塞EndWrite 等待实际写入发生?当套接字 API 中的某种较低级别的缓冲区下溢时会发生这种情况吗?当数据实际写入网络时会发生这种情况吗?确认后是否会发生?

我很困惑,所以这整个问题有可能是离题的。如果是这样,您能否转过身来并指出正确的方向来解决我认为是相当普遍的问题?

【问题讨论】:

    标签: c# .net networking sockets


    【解决方案1】:

    我会更详细地回答你问题的第三部分。

    MSDN 文档指出:

    当您的应用程序调用 BeginWrite 时,系统使用单独的线程执行指定的回调方法,并阻塞 EndWrite,直到 NetworkStream 发送请求的字节数或引发异常。

    据我了解,调用BeginSend后是否立即调用回调方法取决于底层实现和平台。例如,如果 IO 完成端口在 Windows 上可用,则不会。线程池中的线程在调用之前会阻塞。

    事实上,NetworkStream 的 BeginWrite 方法只是在我的 .Net 实现中调用底层套接字的 BeginSend 方法。 Mine 使用带有完成端口的底层 WSASend Winsock 函数(如果可用)。这比简单地为每个发送/写入操作创建自己的线程要高效得多,即使您要使用线程池也是如此。

    然后,如果 WSASend 的结果是 IOPending,则 Socket.BeginSend 方法调用 OverlappedAsyncResult.CheckAsyncCallOverlappedResult 方法,该方法又调用本机 RegisterWaitForSingleObject Win32 函数。这将导致线程池中的一个线程阻塞,直到 WSASend 方法发出它已完成的信号,然后调用回调方法。

    由 NetworkStream.EndSend 调用的 Socket.EndSend 方法将等待发送操作完成。之所以必须这样做是因为如果 IO 完成端口不可用,那么回调方法将被立即调用。

    我必须再次强调,这些细节是特定于我的 .Net 实现和我的平台的,但希望能给您一些见解。

    【讨论】:

      【解决方案2】:

      首先,您的主线程可以在其他工作完成时继续执行的唯一方法是使用另一个线程。一个线程不能同时做两件事。

      但是,我认为您要避免弄乱 Thread 对象,是的,这可以通过使用 BeginWrite 来实现。根据您的问题

      文档不清楚(对我来说) 关于什么时候回调方法 调用。

      在网络驱动程序将数据读入其缓冲区后进行调用。

      它是否基本上立即发生, 就在另一个线程上 EndWrite 上的块等待 实际写作会发生吗?

      不,直到它在网络驱动程序处理的缓冲区中。

      当某种 套接字 API 中的低级缓冲区 下溢?

      如果通过下溢你的意思是它有空间,那么是的。

      当数据被删除时是否会发生 实际写入网络?

      没有。

      当它发生时是否会发生 承认?

      没有。

      编辑

      我个人会尝试使用线程。 BeginWrite 在幕后做了很多你应该知道的事情……而且我很奇怪,我喜欢控制我的线程。

      【讨论】:

      • 这个问题中有一些信息不太准确。例如,正如我在帖子中解释的那样,回调肯定不会总是在数据到达发送缓冲区后立即被调用。这取决于实现,但即使在 Windows 上,也取决于 IO 完成端口是否可用。有时它可能会立即被调用并阻塞 EndWrite。我还要补充一点,为每次发送创建一个线程是不明智的。至少,使用线程池。但是你只是让事情复杂化了,而且很可能比 BeginWrite 效率低。
      猜你喜欢
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-30
      • 1970-01-01
      • 2015-10-01
      相关资源
      最近更新 更多