IO完成端口中的业务逻辑
Business logic in IO completion Port
我对 winsock2 中的 IO Completion Port 和 AcceptEx 有一些疑问
如有错误请指正
AcceptEx是一种接受请求或连接的重叠方式。但是,正如该站点上的多个帖子所指出的那样,如果 AcceptEx 需要数据但连接的客户端未发送数据,AcceptEx
很容易受到 DOS 攻击。那么,是否可以通过在dwReceiveDataLength
?
中输入0来解决?
此外,在接受相应连接时能够从客户端接收数据而不是稍后使用AcceptEx
接收数据有什么优势?
接受来自对端的连接并关联到IO完成端口后,请求将在IO完成端口中作为完成数据包排队,并与各自的句柄关联。阻塞在完成端口上的工作线程将根据 NumberOfConcurrentThreads
被唤醒以服务于请求。那么,完成端口中的线程是IO线程吗?
那么,我应该在socket服务器的什么地方实现业务逻辑或者操作呢?例如,来自客户端的请求将数字发送到服务器进行处理,而服务器则像计算器一样通过回显计算输出进行响应。那么这个逻辑是否可以在IO Completion Port中实现呢?
如果在IO完成端口中实现逻辑(当IO完成端口中活跃的IO线程(假设)正在执行WSARecv
或 WSASend
)), IO threads 是否会在等待计算完成时阻塞从而导致如果积压全部被占用则无法接受任何连接?
已编辑:
- 比如接受客户端socket并在IO完成端口排队/关联后(main_cpl_port),在此 main_cpl_port 上阻塞的线程调用
GetQueuedCompletionStatus
使完成数据包出队,然后将数据读入分配的缓冲区。在将任何响应写回客户端之前,将针对 "command"(例如:GoToCalculator、GoToRecorder)处理/解析缓冲区。
- 例如GoToCalculator负责其他计算相关的命令
- 在这种情况下,GoToCalculator实际上是另一个IO完成端口,可以满足所有与计算相关的请求。假设完成端口被命名为 calc_completion_port.
- 因此,是否可以将来自main_cpl_port的完成数据包发布到calc_completion_port 用于来自当前与 [=93= 关联的客户端套接字的未来 IO(发送和接收) ]。这是
PostQueuedCompletionStatus
的用途吗?
- 从客户端发送到 calc_completion_port 的消息是否可以被阻塞在此完成端口上的线程接收?
换句话说,如何将连接重定向到另一个完成端口?
1) 避免潜在的 AcceptEx DOS 攻击很容易,只要不提供任何 space 数据,AcceptEx 将在连接建立后立即完成。
2) 使用 AcceptEx 意味着您不需要单独的线程来 运行 接受循环。这从您的系统中删除了一个线程并减少了上下文切换。如果您正在侦听多个套接字(不同 ports/interfaces),这将特别有用,因为每个侦听套接字都需要自己的接受线程。
3) 是的,在 IOCP 上调用 GetQueuedCompletionStatus 的工作线程可以被认为是 I/O 个线程...
4) 这取决于。我已经构建了具有不同的、固定大小的 I/O 线程池的系统,这些线程池从不执行任何阻塞操作,并分离扩展线程池来执行阻塞操作。这个想法是这样可以防止所有线程被阻塞并防止I/O ...这需要您将工作项传递给另一个线程池并且它会导致不必要的上下文切换和复杂性但这意味着您总是有线程执行 I/O 操作(例如在 AcceptEx 完成时处理新连接)...当 IOCP API 用于取消未决操作时,如果发出的线程在操作完成。既然 OS 已经改变了规则并且挂起的操作没有被取消,那么没有真正的理由为什么你不只是有一个 expanding/contracting 线程池 I/O 并在那里完成你的所有工作。 .. 您只需要跟踪有多少可用线程和 create/destroy 个线程,因为您需要 expand/contract 您的池...
5) 见 4.
我对 winsock2 中的 IO Completion Port 和 AcceptEx 有一些疑问
如有错误请指正
AcceptEx是一种接受请求或连接的重叠方式。但是,正如该站点上的多个帖子所指出的那样,如果 AcceptEx 需要数据但连接的客户端未发送数据,
AcceptEx
很容易受到 DOS 攻击。那么,是否可以通过在dwReceiveDataLength
? 中输入0来解决?
此外,在接受相应连接时能够从客户端接收数据而不是稍后使用
AcceptEx
接收数据有什么优势?接受来自对端的连接并关联到IO完成端口后,请求将在IO完成端口中作为完成数据包排队,并与各自的句柄关联。阻塞在完成端口上的工作线程将根据
NumberOfConcurrentThreads
被唤醒以服务于请求。那么,完成端口中的线程是IO线程吗?那么,我应该在socket服务器的什么地方实现业务逻辑或者操作呢?例如,来自客户端的请求将数字发送到服务器进行处理,而服务器则像计算器一样通过回显计算输出进行响应。那么这个逻辑是否可以在IO Completion Port中实现呢?
如果在IO完成端口中实现逻辑(当IO完成端口中活跃的IO线程(假设)正在执行
WSARecv
或WSASend
)), IO threads 是否会在等待计算完成时阻塞从而导致如果积压全部被占用则无法接受任何连接?
已编辑:
- 比如接受客户端socket并在IO完成端口排队/关联后(main_cpl_port),在此 main_cpl_port 上阻塞的线程调用
GetQueuedCompletionStatus
使完成数据包出队,然后将数据读入分配的缓冲区。在将任何响应写回客户端之前,将针对 "command"(例如:GoToCalculator、GoToRecorder)处理/解析缓冲区。 - 例如GoToCalculator负责其他计算相关的命令
- 在这种情况下,GoToCalculator实际上是另一个IO完成端口,可以满足所有与计算相关的请求。假设完成端口被命名为 calc_completion_port.
- 因此,是否可以将来自main_cpl_port的完成数据包发布到calc_completion_port 用于来自当前与 [=93= 关联的客户端套接字的未来 IO(发送和接收) ]。这是
PostQueuedCompletionStatus
的用途吗? - 从客户端发送到 calc_completion_port 的消息是否可以被阻塞在此完成端口上的线程接收? 换句话说,如何将连接重定向到另一个完成端口?
1) 避免潜在的 AcceptEx DOS 攻击很容易,只要不提供任何 space 数据,AcceptEx 将在连接建立后立即完成。
2) 使用 AcceptEx 意味着您不需要单独的线程来 运行 接受循环。这从您的系统中删除了一个线程并减少了上下文切换。如果您正在侦听多个套接字(不同 ports/interfaces),这将特别有用,因为每个侦听套接字都需要自己的接受线程。
3) 是的,在 IOCP 上调用 GetQueuedCompletionStatus 的工作线程可以被认为是 I/O 个线程...
4) 这取决于。我已经构建了具有不同的、固定大小的 I/O 线程池的系统,这些线程池从不执行任何阻塞操作,并分离扩展线程池来执行阻塞操作。这个想法是这样可以防止所有线程被阻塞并防止I/O ...这需要您将工作项传递给另一个线程池并且它会导致不必要的上下文切换和复杂性但这意味着您总是有线程执行 I/O 操作(例如在 AcceptEx 完成时处理新连接)...当 IOCP API 用于取消未决操作时,如果发出的线程在操作完成。既然 OS 已经改变了规则并且挂起的操作没有被取消,那么没有真正的理由为什么你不只是有一个 expanding/contracting 线程池 I/O 并在那里完成你的所有工作。 .. 您只需要跟踪有多少可用线程和 create/destroy 个线程,因为您需要 expand/contract 您的池...
5) 见 4.