【问题标题】:Business logic in IO completion PortIO完成端口中的业务逻辑
【发布时间】:2016-06-24 21:34:47
【问题描述】:

我对 IO Completion Port 以及 winsock2 中的 AcceptEx 有一些疑问

如果我错了,请纠正我。

  1. AcceptEx 是一种接受请求或连接的重叠方式。但是,正如该站点上的多个帖子所指出的那样,如果 AcceptEx 期待数据但不是由连接的客户端发送,AcceptEx 很容易受到 DOS 攻击。那么,只要把dwReceiveDataLength加0就可以解决吗?

  2. 此外,在接受相应连接时能够从客户端接收数据而不是稍后使用AcceptEx 接收数据有什么优势?

  3. 在接受来自对端端点的连接并将其与 IO 完成端口相关联后,请求作为完成数据包在 IO 完成端口中排队,这些完成数据包与它们各自的句柄相关联。阻塞在完成端口上的工作线程将根据NumberOfConcurrentThreads 被唤醒以服务请求。那么,完成端口中的线程是IO线程吗?

  4. 那么,应该在socket服务器的什么地方实现业务逻辑或者操作呢?例如,来自客户端的请求将数字发送到服务器进行处理,而服务器就像计算器一样通过回显计算的输出来响应。那么,这个逻辑可以在IO Completion Port中实现吗?

  5. 如果逻辑在 IO 完成端口中实现(当 IO 完成端口中活动的 IO 线程(假定)正在执行 WSARecvWSASend)),会IO线程在等待计算完成时阻塞,因此如果积压全部被占用,则无法接受任何连接?

已编辑:

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

【问题讨论】:

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


    【解决方案1】:

    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.

    【讨论】:

    • 嗨,Len,我对问题中的编辑有一些疑问,希望您能对此有所了解。谢谢
    • IOCP 可用于重叠 I/O,使用 API 将结果发布到 IOCP。这就是 WSARecv() 等的工作方式。它们也可以通过使用 PostQueuedCompletionStatus() 以编程方式用作工作队列。在任何一种情况下,都使用 GetQueuedCompletionStatus() 检索完成。有关工作示例,请参见此处:serverframework.com/…
    猜你喜欢
    • 2014-02-08
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-30
    • 2010-11-13
    • 2014-08-15
    相关资源
    最近更新 更多