这两天粗略的学习了完成端口的简单应用今天把他记下来!

IOCP(I/O CompletionPort) I/O完成端口;

IOCP模型属于一种通讯模型,适用于(能控制并发执行的)高负载服务器的一个技术。一种能够处理很多很多用户的数据交换的一个模型,主要还是异步I/O操作的模型,不过由于是内核操作,很多东西都是windows设计好的,最起码线程安全由系统负责。

主要的优点有:利于管理,分配线程,控制并发,最小化的线程上下文切换。优化线程调度,提高CPU和内存缓冲的命中率。可以帮助维护重复使用的内存池。去除删除线程创建/终结负担。

相对而言:IOCP是一种大规模连接,小数据传送。如果带宽够大,传数据只需几十个或者小于60个,就能搞定,那还不如用I/O事件选择。更快捷、还能保证安全。我们这里应用IOCP应用的是串型传输,可能影响速率,但是保证安全,完整传输。

首先说一下主要用到的API函数,当然主要是关于完成端口的:

最主要的一个函数CreateIoCompletionPort

HANDLE WINAPI  CreateIoCompletionPort(
__in HANDLE FileHandle,                 //关联文件句柄
__in_opt HANDLE ExistingCompletionPort, //已存在的文件句柄
__in ULONG_PTR CompletionKey,           //传送给处理函数的参数 ,是个结构体里面有Client的信息(SOCKET和地址)
__in DWORD NumberOfConcurrentThreads    //有多少个线程在访问这个消息队列
);

下一就是“完成”后的消息的队列,内核完成的操作都在里面,这是I/O操作,用的是异步通信,也就是内核处理数据,线程继续运行,最后完成该线程工作。

BOOL WINAPI GetQueuedCompletionStatus(__in          HANDLE CompletionPort,       // 已建立的文件句柄
  __out         LPDWORD lpNumberOfBytes,     //完成一次I/O操作后,接收实际传输的字节数__out         PULONG_PTR lpCompletionKey,  //完成端口里面的信息地址__out         LPOVERLAPPED* lpOverlapped,  //重叠结构内的信息地址__in          DWORD dwMilliseconds         //处理时间
);

剩下最后一个就是如何正确关闭I/O完成端口

BOOL WINAPI PostQueuedCompletionStatus(__in          HANDLE CompletionPort,__in          DWORD dwNumberOfBytesTransferred,__in          ULONG_PTR dwCompletionKey,__in          LPOVERLAPPED lpOverlapped
);

 

基本样例就是

PostQueuedCompletionStatus(m_hIOCompletionPort, 0, (DWORD) NULL, NULL);  

下面就是具体过程:

一、首先要建立一个完成端口:里面的参数可能都是0和-1,并且确定要创建的线程数(和自己的CPU有直接关系)

二、判断系统内到底多少个处理器

三、根据处理器数量创建线程

四、套接字操作,直接运行到监听完成。

五、使用accept函数,接受入站的连接请求。

六、创建数据结构主要用于容纳单句柄数据,我这里主要涉及到的有SOCKET和ClientAddr。还有重叠数据结构里面涉及到的有LPOVERLAPPED,缓存,类型

七、把ClientSkt和完成端口关联到一起。并且把单句柄数据结构传递进CreateIoCompletionPort();

八、使用重叠I/O,在套接字上投递一个或多个WSASend和WSARecv调用。

九、线程开始运行。如果线程结束,回收堆内存。由于使用的是全局堆栈内存,所以可以在其他地方回收内存。当GetQueueCompletionStatus值为0时,阻塞中,这种情况说的是前面没有运行过,如果在运行中出现为零就需要考虑回收资源。当然还有一种情况就是操作完成时,也要回收资源。

十、关闭I/O完成端口。

这些都是看书,直接总结的,有不足的地方,互相探讨