我想在我的服务器中使用重叠 I/O,但我找不到很多关于该主题的教程(大多数教程都是关于带有完成端口的重叠 I/O,并且我想使用回调函数)。
我的服务器一次最多连接 400 个客户端,并且它仅在很长一段时间内发送和接收数据(服务器和客户端之间每 30 秒交换几千字节的数据)。
我想使用重叠 I/O 的主要原因是因为 select() 最多只能处理 64 个套接字(而我有 400 个!)。
所以我会告诉你我是如何理解重叠I/O的,如果我错了请纠正我:
您似乎存在的一个误解是重叠回调实际上是同步的。
你说:
当数据被接收并填充到缓冲区时,回调函数将被调用
现实:
当调用可警报等待函数(例如
或SleepEx
)时,如果数据已被接收并填充到缓冲区中,则会调用回调函数MsgWaitForMultipleObjectsEx
只要您意识到这一点,您就应该保持良好的状态。 我同意你的观点,在你的场景中,重叠 I/O 与回调是一个很好的方法。 由于回调发生在执行 I/O 的线程上,因此您不必担心同步多个线程的访问,而您需要使用线程池上的完成端口和工作项来同步访问。
哦,还要确保检查
WSA_IO_PENDING
,因为如果已经缓冲了足够的数据(用于接收)或缓冲区中有足够的空间(用于发送),则操作可以同步完成。 在这种情况下,回调将会发生,但它会排队等待下一个可警报的等待,它永远不会立即运行。 某些错误也会同步报告。 其他人会来听你的回电。
此外,还可以保证对于每个返回
0
或 WSA_IO_PENDING
的操作,您的回调只会排队一次,无论该操作成功完成、被取消还是出现其他错误。 在回调发生之前,您无法重用缓冲区。
IO完成回调机制工作正常,我用过几次,没问题。 在 32 位系统中,您可以将套接字上下文实例的“this”放入 OVERLAPPED 结构的 hEvent 字段中,并在回调中检索它。 不知道如何在 64 位系统中执行此操作:(