HANDLE WINAPI CreateIoCompletionPort(
__in HANDLE FileHandle,
__in_opt HANDLE ExistingCompletionPort,
__in ULONG_PTR CompletionKey,
__in DWORD NumberOfConcurrentThreads
);
CreateIoCompletionPort:这个函数有两个功能,一个是创建最初的IoComplete对象,这时没有任何IO文件句柄被加入进去。一个是将一个overlap的IO文件,加入到IoComplete对象。
下面的代码是创建一个IO completion port。
{
HANDLE cp;
number_of_max_thread = 10; //假定只有10个线程可以访问该对象
cp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, number_of_max_thread);
}
其中FileHandle和ExistingCompletionPort两个参数传入的值表示的是该函数将创建一个新的完成端口。
下面代码是将socket端口加入到完成端口中。
{
struct ioev_struct
{
int sockect;
WSAOVERLAPPED Overlapped;
};
HANDLE cp;
int socketfd; //该socketfd为通过accept得到的客户端连入端口
struct ioev_struct *ioev = malloc(sizeof(struct ioev_struct)); //自定义结构的,用于和socketfd关联
Ioev->sockect = socketfd;
cp2 = CreateIoCompletionPort(socketfd, cp , ioev , 0);
}
此时完成了将变量socketfd端口加入到cp(上一段例子代码中生成的cp句柄)中,同时将ioev也传入,ioev指针将在socketfd出现io事件后,通过GetQueuedCompletionStatus返回。不过此时还不能监听socketfd上的事件。还需要下一步的步骤
将io端口投递到完成端口
{
DWORD dwRecvNumBytes = 0;
int nRet = 0;
DWORD dwFlags = 0;
WSABUF wsabuf;//overlap所需的缓冲区,可查看相应的定义
nRet = WSARecv(socketfd, wsabuf, 1, &dwRecvNumBytes, &dwFlags,
&ioev->Overlapped, NULL);
}
其中ioev 是上段代码定义的ioev变量,在这里ioev->Overlapped是overlap的结构,用于后面GetQueuedCompletionStatus返回overlap的数据。记住,必须保持该部分空间的有效性,直到不再使用GetQueuedCompletionStatus获得数据。
等待事件发生
{
LPWSAOVERLAPPED lpOverlapped = NULL;
BOOL bSuccess = FALSE;
DWORD dwIoSize = 0;
struct ioev_struct *ioev;
bSuccess = GetQueuedCompletionStatus(cp, &dwIoSize,
(PDWORD_PTR)&ioev,
&lpOverlapped,
INFINITE);
//根据ioev进行处理。
}
cp是之前生成的完成端口,ioev将获得绑定到端口上的ioev对象,lpOverlapped将获得在WSARecv中指定的overlap结构。