1、WinSocket 模型的探讨完成端口模型众所皆知,完成端口是在 WINDOWS 平台下效率最高,扩展性最好的 IO 模型,特别针对于 WINSOCK 的海量连接时,更能显示出其威力。其实建立一个完成端口的服务器也很简单,只要注意几个函数,了解一下关键的步骤也就行了。这是篇完成端口入门级的文章,分为以下几步来说明完成端口: 函数 常见问题以及解答 步骤 例程 1、函数:我们在完成端口模型下会使用到的最重要的两个函数是:CreateIoCompletionPort、GetQueuedCompletionStatusCreateIoCompletionPort 的作用是创建一个完成端口和把一个 I
2、O 句柄和完成端口关联起来:/ 创建完成端口HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);/ 把一个 IO 句柄和完成端口关联起来,这里的句柄是一个 socket 句柄CreateIoCompletionPort(HANDLE)sClient, CompletionPort, (DWORD)PerHandleData, 0);其中第一个参数是句柄,可以是文件句柄、SOCKET 句柄。第二个就是我们上面创建出来的完成端口,这里就把两个东西关联在一起了。第三个参数很关键,叫做 Per
3、HandleData,就是对应于每个句柄的数据块。我们可以使用这个参数在后面取到与这个 SOCKET 对应的数据。最后一个参数给 0,意思就是根据 CPU 的个数,允许尽可能多的线程并发执行。GetQueuedCompletionStatus 的作用就是取得完成端口的结果:/ 从完成端口中取得结果GetQueuedCompletionStatus(CompletionPort, / 宏定义#define PORT 5050#define DATA_BUFSIZE 8192#define OutErr(a) cout Socket Socket);delete PerIoData;delete
4、PerHandleData;continue;elseOutErr(“GetQueuedCompletionStatus failed!“);return 0;/ 说明客户端已经退出if(BytesTransferred = 0)cout Socket Socket);delete PerIoData;delete PerHandleData;continue;/ 取得数据并处理cout Socket Buffer DataBuf.buf = PerIoData-Buffer;PerIoData-DataBuf.len = DATA_BUFSIZE;WSARecv(PerHandleData-
5、Socket, return 0;void main()InitWinsock();HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);/ 根据系统的 CPU 来创建工作者线程SYSTEM_INFO SystemInfo;GetSystemInfo(for(int i = 0; i Socket = sClient;/ 将接入的客户端和完成端口联系起来CreateIoCompletionPort(HANDLE)sClient, CompletionPort, (DWORD)PerHan
6、dleData, 0);/ 建立一个 Overlapped,并使用这个 Overlapped 结构对 socket 投递操作PerIoData = new PER_IO_OPERATION_DATA();ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA);PerIoData-DataBuf.buf = PerIoData-Buffer;PerIoData-DataBuf.len = DATA_BUFSIZE;/ 投递一个 WSARecv 操作DWORD Flags = 0;DWORD dwRecv = 0;WSARecv(sClient, DWORD dwByteTrans;PostQueuedCompletionStatus(CompletionPort, dwByteTrans, 0, 0);closesocket(sListen);好了,本篇文章就到此为止,以后有时间再继续写下一篇,下篇就不是这种步骤和函数的说明了,而是包括了封装、架构、应用等等方面的技术。OK ,下次再会!本文来自 CSDN 博客,转载请标明出处:http:/