如何使用 Overlapped I/O 与套接字?
How to use Overlapped I/O with sockets?
我想在我的服务器中使用 Overlapped I/O,但是我找不到很多关于这个主题的教程(大多数教程都是关于 Overlapped I/O with Completion Ports,我想要使用回调函数)。
我的服务器一次最多连接 400 个客户端,并且它只在很长一段时间内发送和接收数据(服务器和客户端之间每 30 秒交换几千字节的数据).
我想使用 Overlapped I/O 的主要原因是因为 select()
最多只能处理 64 个套接字(而我有 400 个!)。
所以我会告诉你我是如何理解 Overlapped I/O 如果我错了请纠正我:
- 如果我想从其中一个客户端接收数据,我使用
WSARecv()
并提供套接字句柄,以及一个用于填充接收到的数据的缓冲区, 我还提供一个回调函数。当接收到数据并填入缓冲区后,就会调用回调函数,我就可以处理数据了。
- 当我想发送数据时我使用
WSASend()
,我还提供套接字句柄和回调函数,以及何时发送数据(不确定是放在底层发送缓冲区中还是实际放置线上),回调也会被调用,告诉我数据已发送,我可以发送下一条数据。
您似乎存在的一个误解是 OVERLAPPED 回调实际上是同步的。
你说:
When the data is received and filled in the buffer, the callback function will be called
现实:
When a call is made to an alertable wait function (e.g. SleepEx
or MsgWaitForMultipleObjectsEx
), if data has been received and filled in the buffer, the callback function will be called
只要你意识到这一点,你应该处于良好状态。我同意你的观点,I/O 与回调重叠在你的场景中是一种很好的方法。因为回调发生在执行 I/O 的线程上,所以您不必担心来自多个线程的同步访问,这是您需要在线程池上使用完成端口和工作项的方式。
哦,还要确保检查 WSA_IO_PENDING
,因为操作可能会同步完成,如果已经缓冲了足够的数据(用于接收)或缓冲区中有足够的 space(用于接收)发送)。在这种情况下,回调将发生,但它会排队等待下一个可警告的等待,它不会立即运行。某些错误也会同步报告。其他人会来回电。
此外,对于返回 0
或 WSA_IO_PENDING
的每个操作,无论该操作是成功完成、被取消还是出现其他错误,都保证您的回调只排队一次。在回调发生之前,您不能重用缓冲区。
IO完成回调机制很好用,我用过几次,没问题。在 32 位系统中,您可以将套接字上下文实例的 'this' 放入 OVERLAPPED 结构的 hEvent 字段中,并在回调中检索它。不确定如何在 64 位系统中执行此操作:(
我想在我的服务器中使用 Overlapped I/O,但是我找不到很多关于这个主题的教程(大多数教程都是关于 Overlapped I/O with Completion Ports,我想要使用回调函数)。
我的服务器一次最多连接 400 个客户端,并且它只在很长一段时间内发送和接收数据(服务器和客户端之间每 30 秒交换几千字节的数据).
我想使用 Overlapped I/O 的主要原因是因为 select()
最多只能处理 64 个套接字(而我有 400 个!)。
所以我会告诉你我是如何理解 Overlapped I/O 如果我错了请纠正我:
- 如果我想从其中一个客户端接收数据,我使用
WSARecv()
并提供套接字句柄,以及一个用于填充接收到的数据的缓冲区, 我还提供一个回调函数。当接收到数据并填入缓冲区后,就会调用回调函数,我就可以处理数据了。 - 当我想发送数据时我使用
WSASend()
,我还提供套接字句柄和回调函数,以及何时发送数据(不确定是放在底层发送缓冲区中还是实际放置线上),回调也会被调用,告诉我数据已发送,我可以发送下一条数据。
您似乎存在的一个误解是 OVERLAPPED 回调实际上是同步的。
你说:
When the data is received and filled in the buffer, the callback function will be called
现实:
When a call is made to an alertable wait function (e.g.
SleepEx
orMsgWaitForMultipleObjectsEx
), if data has been received and filled in the buffer, the callback function will be called
只要你意识到这一点,你应该处于良好状态。我同意你的观点,I/O 与回调重叠在你的场景中是一种很好的方法。因为回调发生在执行 I/O 的线程上,所以您不必担心来自多个线程的同步访问,这是您需要在线程池上使用完成端口和工作项的方式。
哦,还要确保检查 WSA_IO_PENDING
,因为操作可能会同步完成,如果已经缓冲了足够的数据(用于接收)或缓冲区中有足够的 space(用于接收)发送)。在这种情况下,回调将发生,但它会排队等待下一个可警告的等待,它不会立即运行。某些错误也会同步报告。其他人会来回电。
此外,对于返回 0
或 WSA_IO_PENDING
的每个操作,无论该操作是成功完成、被取消还是出现其他错误,都保证您的回调只排队一次。在回调发生之前,您不能重用缓冲区。
IO完成回调机制很好用,我用过几次,没问题。在 32 位系统中,您可以将套接字上下文实例的 'this' 放入 OVERLAPPED 结构的 hEvent 字段中,并在回调中检索它。不确定如何在 64 位系统中执行此操作:(