[摘錄]
IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型。它是应用程序使用线程池处理异步I/O请求的一种机制。在处理多个并发的异步I/O请求时,以往的模型都是在接收请求是创建一个线程来应答请求。这样就有很多的线程并行地运行在系统中。而这些线程都是可运行的,Windows内核花费大量的时间在进行线程的上下文切换,并没有多少时间花在线程运行上。再加上创建新线程的开销比较大,所以造成了效率的低下。
而IOCP模型是事先开好了N个线程,存储在线程池中,让他们hold。然后将所有用户的请求都投递到一个完成端口上,然后N个工作线程逐一地从完成端口中取得用户消息并加以处理。这样就避免了为每个用户开一个线程。既减少了线程资源,又提高了线程的利用率。
IOCP模型的实现:
1. 创建一个完成端口
FCompletPort := CreateIoCompletionPort( INVALID_HANDLE_VALUE, 0,0,0 );
HANDLE CreateIoCompletionPort (
HANDLE FileHandle, // 和IOCP關聯的文件句柄
HANDLE ExistingCompletionPort, // 已經存在的IOCP句柄, 可選
DWORD CompletionKey, //
DWORD NumberOfConcurrentThreads // 允許同時並行的線程數, 理論值是 CPU*2+2
);
此函數完成如下任務:
1.用于创建一个完成端口对象
2.将一个句柄[HANDLE]和完成端口关联到一起
2. 创建CPU数*2 + 2个线程
for i:=1 to si.dwNumberOfProcessors*2+2 do
begin
AThread := TRecvSendThread.Create( false );
AThread.CompletPort := FCompletPort; //告诉这个线程,你要去这个IOCP去访问数据
end; 3. 接受远程连接,并把这个连接的socket句柄绑定到刚才创建的IOCP上
AConnect := accept( FListenSock, addr, len);
CreateIoCompletionPort( AConnect, FCompletPort, nil, 0 );
procedure TRecvSendThread.Execute;
var
......
begin
while (not self.Terminated) do // 循環執行
begin //查询IOCP状态(数据读写操作是否完成)
GetQueuedCompletionStatus( CompletPort, BytesTransd, CompletKey, POVERLAPPED(pPerIoDat), TMME_OUT );
if BytesTransd <> 0 then ....;//数据读写操作完成
//再投递一个读数据请求
WSARecv( CompletKey, @(pPerIoDat^.BufData), 1, BytesRecv, Flags, @(pPerIoDat^.Overlap), nil );
end;
end;
另一個 IOCP 方法:
BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort, // IOCP 句柄
LPDWORD lpNumberOfBytes, // 傳輸的字節數, bytes transferred
PULONG_PTR lpCompletionKey, // file completion key
LPOVERLAPPED *lpOverlapped, // buffer
DWORD dwMilliseconds // optional timeout value
);