如何通过套接字使用重叠 I/O?

问题描述 投票:0回答:2

我想在我的服务器中使用重叠 I/O,但我找不到很多关于该主题的教程(大多数教程都是关于带有完成端口的重叠 I/O,并且我想使用回调函数)。

我的服务器一次最多连接 400 个客户端,并且它仅在很长一段时间内发送和接收数据(服务器和客户端之间每 30 秒交换几千字节的数据)。

我想使用重叠 I/O 的主要原因是因为 select() 最多只能处理 64 个套接字(而我有 400 个!)。

所以我会告诉你我是如何理解重叠I/O的,如果我错了请纠正我:

  • 如果我想从其中一个客户端接收数据,我使用 WSARecv() 并提供套接字句柄,以及一个用接收到的数据填充的缓冲区,我还提供一个回调函数。当数据被接收并填充到缓冲区时,回调函数将被调用,我就可以处理数据了。
  • 当我想发送数据时,我使用WSASend(),我还提供了套接字句柄和回调函数,以及何时发送数据(不确定是否放置在底层发送缓冲区中或实际放置在线),回调也会被调用,告诉我数据已发送,我可以发送下一条数据。
c++ windows sockets winapi network-programming
2个回答
4
投票

您似乎存在的一个误解是重叠回调实际上是同步的。

你说:

当数据被接收并填充到缓冲区时,回调函数将被调用

现实:

当调用可警报等待函数(例如

SleepEx
MsgWaitForMultipleObjectsEx
)时,如果数据已被接收并填充到缓冲区中,则会调用回调函数

只要您意识到这一点,您就应该保持良好的状态。 我同意你的观点,在你的场景中,重叠 I/O 与回调是一个很好的方法。 由于回调发生在执行 I/O 的线程上,因此您不必担心同步多个线程的访问,而您需要使用线程池上的完成端口和工作项来同步访问。

哦,还要确保检查

WSA_IO_PENDING
,因为如果已经缓冲了足够的数据(用于接收)或缓冲区中有足够的空间(用于发送),则操作可以同步完成。 在这种情况下,回调将会发生,但它会排队等待下一个可警报的等待,它永远不会立即运行。 某些错误也会同步报告。 其他人会来听你的回电。

此外,还可以保证对于每个返回

0
WSA_IO_PENDING
的操作,您的回调只会排队一次,无论该操作成功完成、被取消还是出现其他错误。 在回调发生之前,您无法重用缓冲区。


0
投票

IO完成回调机制工作正常,我用过几次,没问题。 在 32 位系统中,您可以将套接字上下文实例的“this”放入 OVERLAPPED 结构的 hEvent 字段中,并在回调中检索它。 不知道如何在 64 位系统中执行此操作:(

© www.soinside.com 2019 - 2024. All rights reserved.