IO完成端口

时间:2016-03-10 07:04:22

标签: c++ winsock2 asyncsocket overlapped-io io-completion-ports

我对IO完成端口以及winsock2中的AcceptEx有疑问

如果我错了,请纠正我。

  1. AcceptEx是一种接受请求或连接的重叠方式。但是,正如本网站上的多个帖子所指出的,AcceptEx如果AcceptEx期待数据但不是由连接的客户端发送,则容易发生DOS攻击。那么,只需将0添加到dwReceiveDataLength

  2. 即可解决
  3. 此外,在接受相应连接时能够从客户端接收数据而不是稍后使用AcceptEx接收数据有什么好处?

  4. 接受来自对端端点的连接并将其与IO完成端口关联后,请求将在IO完成端口中排队,作为与其各自句柄关联的完成数据包。阻塞在完成端口上的工作线程将被唤醒,具体取决于NumberOfConcurrentThreads以提供请求。那么,完成端口中的线程是 IO线程吗?

  5. 那么,我应该在哪里实现套接字服务器中的业务逻辑或操作?例如,客户端发送数字到服务器进行处理的请求,而服务器就像计算器一样,通过回显计算的输出来响应。因此,这个逻辑可以在IO完成端口中实现吗?

  6. 如果逻辑在IO完成端口中实现(当 IO线程(假设)在IO完成端口中处于活动状态时执行WSARecvWSASend) ), IO线程会在等待计算完成时阻塞,因此如果积压全部都没有接受连接吗?

  7. 编辑:

    • 例如,在接受客户端套接字并在IO完成端口( main_cpl_port )中排队/关联后,阻止此 main_cpl_port的线程 调用GetQueuedCompletionStatus使完成数据包出列,然后将数据读入已分配的缓冲区。在将任何响应写回客户端之前,缓冲区将被处理/解析为“command”(例如:GoToCalculator,GoToRecorder)。
    • 例如,GoToCalculator负责其他与计算相关的命令。
    • 在这种情况下,GoToCalculator实际上是另一个IO完成端口,它满足所有与计算相关的请求。假设完成端口命名为 calc_completion_port
    • 因此,是否有可能将来自 main_cpl_port 的完成数据包发布到 calc_completion_port 以用于将来的IO (发送和接收)来自当前与 main_cpl_port 相关联的客户端套接字。这是PostQueuedCompletionStatus用于什么?
    • 发布到 calc_completion_port 之后从客户端发送的消息是否可以被阻止在此完成端口上的线程接收? 换句话说,如何将连接重定向到另一个完成端口?

1 个答案:

答案 0 :(得分:3)

1)避免潜在的AcceptEx DOS攻击很容易,只是没有为数据提供任何空间,一旦建立连接,AcceptEx就会完成。

2)使用AcceptEx意味着您不需要单独的线程来运行接受循环。这将从系统中删除一个线程并减少上下文切换。如果您正在侦听多个套接字(不同的端口/接口),这尤其有用,因为每个侦听套接字都需要自己的接受线程。

3)是的,在IOCP上调用GetQueuedCompletionStatus的工作线程可以被认为是I / O线程......

4)这取决于。我构建了具有不同的,固定大小的I / O线程池的系统,它们从不执行任何阻塞操作和单独的扩展线程池,旨在执行阻塞操作。这个想法是这会阻止所有线程被阻塞并阻止I / O ......这要求你将工作项传递给另一个线程池,这会导致不必要的上下文切换和复杂性,但这意味着你总是有线程执行I / O操作(例如在AcceptEx完成时处理新连接)...当IOCP API用于取消挂起操作时,如果在操作完成之前发出的线程退出,则这种设计过去很好。既然操作系统已经改变了规则并且暂停操作没有被取消,那么你没有真正的原因就是不要只有一个扩展/收缩的I / O线程池来完成你所有的工作......您只需要跟踪可用的线程数,并在需要扩展/收缩池时创建/销毁线程......

5)见4。