【问题标题】:select() equivalence in I/O Completion PortsI/O 完成端口中的 select() 等效性
【发布时间】:2014-06-26 15:16:37
【问题描述】:

我正在 Windows 中使用 WinSock 2.0 开发代理服务器。如果我想在阻塞模型中开发它, select() 是等待客户端或远程服务器接收数据的方式。是否有任何适用的方法可以使用 I/O 完成端口来做到这一点?

我曾经使用 I/O 完成端口为两个数据方向提供两个上下文。但是挂起的 WSARecv 无法从远程服务器接收任何数据!没找到问题。

提前致谢。

编辑。 Here 是当前开发的 I/O 完成端口上的 WorkerThread 代码。但我问的是如何实现 select() 等价。

【问题讨论】:

  • 请出示您的代码
  • 你没有运气,完成端口等待完成,而不是准备就绪。使用完成端口获得类似select 的语义的唯一方法是在单独的线程中实际使用select(或WaitFor...)并将自定义完成事件发布到端口。当然,这完全是愚蠢的,并且首先破坏了使用完成端口的目的。
  • @Damon 感谢您的回答 :) 我使用了零字节接收并且它有效 :)

标签: c sockets winapi winsock winsock2


【解决方案1】:

I/O 完成端口提供 I/O 操作何时完成的指示,它们不指示何时可以启动操作。在许多情况下,这实际上并不重要。大多数情况下,如果您假设始终可以启动操作,则重叠 I/O 模型将运行良好。在大多数情况下,底层操作系统会简单地做正确的事情并为您排队数据,直到可以完成操作。

但是,在某些情况下,这并不理想。例如,您始终可以使用重叠 I/O 发送到套接字。即使远程对等方未读取并且 TCP 堆栈已开始使用流量控制并已填满 TCP 窗口,您也可以这样做......这只是以完全不受控制的方式使用本地计算机上的资源(不是完全不受控制,而是由对等体控制,这是不理想的)。我写了这个here,在许多情况下,您确实需要通过跟踪您有多少未完成的 I/O 写入请求并将其用作“准备发送”的指示来积极管理此类事情。

同样,如果您想要“准备接收”指示,您可以在套接字上发出“零字节”读取。这是使用零长度缓冲区发出的读取。当有数据要读取但没有数据返回时,读取返回。这将向您表明连接上有要读取的数据,但是恕我直言,除非您遇到极不可能的情况,即遇到I/O page lock limit,否则您也可以在数据可用时读取数据而不是强制多个内核转换到用户模式。

总而言之,您实际上并不需要您的问题的答案。您需要了解 API 的工作原理并编写代码以使用它,而不是试图强制 API 以您熟悉的其他 API 的方式工作。

【讨论】:

  • 关于“做一个零字节读取以检查准备就绪”的轻微添加:这对 TCP 工作正常,但要小心使用 UDP 做这样的事情,它会丢弃每次做一个数据报!
  • 感谢您的回答。你的文章也很棒:)
猜你喜欢
  • 2011-02-17
  • 2013-01-04
  • 1970-01-01
  • 1970-01-01
  • 2012-06-04
  • 1970-01-01
  • 2012-06-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多