使用 IOCP 的另一个 TCP 回显服务器
IOCP 网络服务器编写入门
引言
本技巧展示了一个非常简单的非阻塞 TCP 回显服务器,它使用 Windows 输入/输出完成端口 (IOCP),能够同时处理任意数量的客户端。
背景
IOCP 通常被认为是编写高性能、高可扩展性 Windows 网络服务器的最佳(有些人会说唯一)方法。但互联网上很少有易于理解的 IOCP 使用示例。
本技巧旨在填补这一空白,提供一个非常简单的 C 语言 IOCP 服务器示例。无需学习类,无需担心其他 Windows API,无需线程处理来增加复杂性,只有两个与 IOCP 相关的函数:CreateIoCompletionPort
和 GetQueuedCompletionStatus
。当然,也使用了 Winsock 异步风格的常用套接字 API:AcceptEx
、listen
、bind
、WSARecv
和 WSASend
。
描述
回显服务器的一般控制流程如下所示
1. initialize Winsock (WSAStartup)
2. create the I/O Completion Port (CreateIoCompletionPort)
3. create the listening socket (listen)
4. associate the listening socket with the IOCP (CreateIoCompletionPort)
5. bind the listening socket (bind)
6. start listening (listen)
7. create a pointer to the AcceptEx function (!)
8. start accepting a new connection (asynchronous AcceptEx)
// the completion status for AcceptEx will be reported through
// the listen IOCP completion status (see step 4)
9. wait for a completion port status (GetQueuedCompletionStatus)
9.1 if the completion status is for an accept (an AcceptEx has completed)
9.1.1 "update the context" of the new socket (whatever that is...)
9.1.2 associate the new socket with the completion port
9.1.3 start reading from the new socket (asynchronous WSARecv)
9.1.4 start accepting another connection (asynchronous AcceptEx)
9.1.5 go to step 9
9.2 if the completion status is for a read (a WSARecv has completed)
9.2.1 start writing to the socket through which the data arrived,
echoing back the data (asynchronous WSASend)
9.2.2 go to step 9
9.3 if the completion status is for a write (a WSASend has completed)
9.3.1 start reading again from the socket that was used to send the data
(asynchronous WSARecv)
9.3.2 go to step 9
就是这样!当然,还有所有需要处理的错误情况,以及一些用于跟踪连接的代码,但总而言之,上述伪代码总结了大部分程序代码。需要注意的是,所有操作都必须是“重叠的”(Windows 中的一种异步 I/O 操作)。
此外,还有一个小型客户端程序(未使用 IOCP),可用于测试回显服务器。
结论
IOCP 易于使用,并且随本技巧一起提供的程序旨在展示如何操作。
您可以从 这里 下载代码。