1.iocp是用于windows的io异步机制,与reactor的区别是:
iocp:
reactor:
2.网络编程要解决的问题
先来看具体的阻塞式io的工作模式:
阻塞式io有四个问题:连接的建立/断开,数据的接收/发送,这四个都不知道何时发生,所以内核只能阻塞在这个地方等待事件发生。
我们再回过头来看reactor与io_cp,就会发现两者的不同之处:
(1)reactor是同步的io,异步的事件。reactor在进行io操作时候是异步的,而事件完成的通知是同步的,通过epoll_wait监视事件的状态
(2)而iocp(proactor)则是异步的io操作,应用程序通过提交请求(如 WSARecv
)直接发起 I/O 操作,操作系统在后台完成所有操作(如数据读取、写入),完成后通知应用程序事件通知也是异步的,通过获取完成队列里的数据获取结果。
3.iocp的具体工作流程
配合下面两张图看:
常用的接口:
1. CreateIoCompletionPort
功能:
创建或关联一个I/O完成端口,用于管理异步I/O操作。
参数:
FileHandle
:要关联的设备句柄(如Socket)。
ExistingCompletionPort
:已有的完成端口句柄。若为NULL
,则创建新的完成端口。
CompletionKey
:用户自定义的标识符(如指向连接上下文的指针)。
NumberOfConcurrentThreads
:允许同时处理完成端口的线程数。通常设为0
(系统自动选择最优值)。
2. GetQueuedCompletionStatus
功能:
从完成端口队列中取出一个完成的I/O操作事件。
参数:
lpNumberOfBytesTransferred
:返回本次I/O操作传输的字节数。
lpCompletionKey
:返回关联时的CompletionKey
(如连接上下文)。
lpOverlapped
:返回提交I/O时的OVERLAPPED
结构指针。
dwMilliseconds
:等待超时时间(毫秒)。INFINITE
表示无限等待。
3. WSARecv
/ WSASend (WSARecv不可以多次投递)
功能:
发起异步的接收/发送数据操作。
参数:
lpBuffers
:指向WSABUF
数组的指针,包含数据缓冲区。
lpOverlapped
:指向OVERLAPPED
结构的指针(需自定义扩展)。
lpCompletionRoutine
:完成回调函数(IOCP中通常设为NULL
)。
整体的工作流程:
(1)连接建立:
socket 与 iocp 绑定,重叠io,一个io可以投递多个请求堆叠在一起 AcceptEx,GetQueuedCompletionStatus(只能拿到一个完成通知) 拿到的完成通知,只完成了一个,服务端启动的时候,通常投递多个 AcceptEx,就可以并发接收多条连接
(2)关联
通过重叠io的指针把io关联到IOCP里
(3)连接断开:服务端被动断开客户端连接 客户端主动断开连接
1. reactor
a. epoll_wait EPOLLHUP\EPOLLRDHUP
b. read、recv 返回值为 0
2. iocp
a. GetLastError WAIT_TIMEOUT (超时)或者 ERROR_NETNAME_DELETED(异常退出)
b. (0 == dwBytes) && (IO_OP_TYPE::IO_RECV == ioContext->type 或IO_OP_TYPE::IO_SEND == ioContext->type)