Windows的iocp核心

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结构。

你可能感兴趣的:(windows)