Socket IO模型之IOCP

    1、IOCP

    IOCP(完成端口)是迄今为止最为复杂的一种I/O模型。然而,假若一个应用程序同时需要管理为数众多的套接字,那么采用这种模型,往往可以达到最佳的系统性能!但不幸的是,该模型只适用于Windows NT和Windows 2000操作系统。因其设计的复杂性,只有在你的应用程序需要同时管理数百乃至上千个套接字的时候,而且希望随着系统内安装的CPU数量的增多,应用程序的性能也可以线性提升,才应考虑采用IOCP。要记住的一个基本准则是,假如要为Windows NT或Windows 2000开发高性能的服务器应用,同时希望为大量套接字I/O请求提供服务,那么I/O完成端口模型便是最佳选择!

 

    2、应用

    从本质上讲,IOCP要求创建一个windows对象,该对象通过指定数量的线程,对重叠I/O请求进行管理,以便为已经完成的重叠I/O请求提供服务。创建IOCP的API函数:

CreateIoCompletionPort(
    __in     HANDLE FileHandle,
    __in_opt HANDLE ExistingCompletionPort,
    __in     ULONG_PTR CompletionKey,
    __in     DWORD NumberOfConcurrentThreads
    );

    该函数能实现两个截然不同的目的:(1)创建一个IOCP对象;(2)将一个句柄与IOCP关联在一起。

    创建一个对象时,比较使人感兴趣的参数是NumberOfConcurrentThreads。该参数的特殊之处在于:在IOCP上同时允许执行线程的数量。通常将其设为0,表示有多少个处理器,则允许同时允许多少个线程。下面语句将创建一个IOCP:

::CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

    其结果是返回一个句柄,用来对端口进行标识。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
IOCP是一种高效的I/O多路复用模型,适用于Windows系统上的网络编程。下面是一个简单的使用IOCP模型的C代码示例,实现了一个简单的回显服务器: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <winsock2.h> #include <windows.h> #define BUFSIZE 1024 typedef struct _PER_HANDLE_DATA { SOCKET Socket; SOCKADDR_STORAGE ClientAddr; } PER_HANDLE_DATA, *LPPER_HANDLE_DATA; typedef struct _PER_IO_DATA { OVERLAPPED Overlapped; WSABUF DataBuf; char Buffer[BUFSIZE]; int OperationType; } PER_IO_DATA, *LPPER_IO_DATA; DWORD WINAPI WorkerThread(LPVOID lpParam); int main(int argc, char* argv[]) { WSADATA wsaData; SOCKET ListenSocket, AcceptSocket; SOCKADDR_STORAGE LocalAddr, ClientAddr; DWORD Flags; LPPER_HANDLE_DATA PerHandleData; LPPER_IO_DATA PerIoData; DWORD RecvBytes, SendBytes; DWORD BytesTransferred; DWORD ThreadId; HANDLE CompletionPort, ThreadHandle; int i; // 初始化Winsock if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { printf("WSAStartup failed with error: %d\n", WSAGetLastError()); return 1; } // 创建完成端口 CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); if (CompletionPort == NULL) { printf("CreateIoCompletionPort failed with error: %d\n", GetLastError()); return 1; } // 创建监听套接字 ListenSocket = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (ListenSocket == INVALID_SOCKET) { printf("socket failed with error: %d\n", WSAGetLastError()); return 1; } // 绑定地址并监听 memset(&LocalAddr, 0, sizeof(LocalAddr)); LocalAddr.ss_family = AF_INET6; ((SOCKADDR_IN6*)&LocalAddr)->sin6_port = htons(12345); ((SOCKADDR_IN6*)&LocalAddr)->sin6_addr = in6addr_any; if (bind(ListenSocket, (SOCKADDR*)&LocalAddr, sizeof(LocalAddr)) == SOCKET_ERROR) { printf("bind failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); return 1; } if (listen(ListenSocket, SOMAXCONN) == SOCKET_ERROR) { printf("listen failed with error: %d\n", WSAGetLastError()); closesocket(ListenSocket); return 1; } // 创建工作线程 for (i = 0; i < 2; i++) { ThreadHandle = CreateThread(NULL, 0, WorkerThread, CompletionPort, 0, &ThreadId); if (ThreadHandle == NULL) { printf("CreateThread failed with error: %d\n", GetLastError()); return 1; } CloseHandle(ThreadHandle); } // 接受连接并关联到完成端口 while (1) { AcceptSocket = accept(ListenSocket, (SOCKADDR*)&ClientAddr, NULL); if (AcceptSocket == INVALID_SOCKET) { printf("accept failed with error: %d\n", WS
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值