完成端口模型

1.API函数
1).创建I/O完成端口对象
HANDLE CreateIoCompletionPort(
 HANDLE FileHandle,
 HANDLE ExistingCompletionPort,
 DWORD  CompletionKey,
 DWORD  NumberOfConcurrentThreads
);
说明:FileHandle指定一个同完成端口关联在一起的套接字句柄;ExistingcompletionProt指定是一个现在有的完成端口;CompletionKey指定要与某个特定套接字句柄关联在一起的“单句柄数据”
2)获取排队完成状态
BOOL GetQueuedCompletionStatus(
 HANDLE CompletionProt,
 LPDWORD lpNumberOfBytesTransferred,
 LPDWORD lpCompletionKey,
 LPOVERLAPPED * lpOverlapped,
 DWORD dwMilliseconds
);
2.步骤&伪代码
1)创建一个完成端口,第四个参数保持为0,指定在完成端口上,每个处理器一次只允许执行一个工作线程。
2)判断系统内到底安装了多少个处理其。
3)创建工作者线程,根据步骤2)得到的处理器信息,在完成端口上,为已完成的I/O请求提供服务。
4)准备好一个监听套接字,监听进入的连接请求。
5)使用accept函数,接收进入的连接请求。
6)创建一个数据结构,用于容纳“单句柄数据”,同时在结构中存入接收的套接字句柄。
7)调用CreateIoCompletionPort,将自accept返回的新套接字句柄同完成端口关联到一起。通过CompletionKey将单句柄数据结构传递给CreateIoCompletionPort。
8)开始在已接收的连接上进行I/O操作。
9)重复步骤5)~8)。

示例:

StartWinsock();

//Step 1:
//Create an I/O Completion port
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
//Step 2:
GetSystemInfo(&SystemInfo);
//Step3
for(i = 0; i< SystemInfo.dwNumberOfProcessors;  i++)
{
 HANDLE ThreadHandle;
 //NOTE: the ServerWorkerThread procedure is not defined
 //in this listing.
 ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,CompletionPort,0,&ThreadID);
 CloseHandle(ThreadHandle);
}

//Step4
Listen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr = htoml(INADDR_ANY);
InternetAddr.sin_port = htonl(5000);
bind(Listen,(SOCKADDR)&InternetAddr,sizeof(InternetAddr));

listen(Listen,5);
while(TRUE)
{
 //Step 5:
 Accept = WSAAccept(Listen,NULL,NULL,NULL,0);

 //Step 6:
 //Create per-handle data information structure to
 //associate with the socket
 PerHandleData = (LPPER_HANDLE_DATA)
  GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
 //Socket connected
 PerHandleData->Socket = Accept;

 //Step 7:
 CreateIoCompletionPort((HANDLE)Accept,CompletionPort,(DWORD)PerHandleData,0);

 //Step 8:
 //Start processing I/O on the accepted socket.
 //Post one or more WSASend() or WSARecv()calls
 //on the socket using overlapped I/O
 WSARecv(...);
}

//---------------------------------------------------------------

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
 HANDLE CompletionPort = (HANDLE)CompletionPortID;
 DWORD BytesTransferred;
 LPOVERLAPPED Overlapped;
 LPPER_HANDLE_DATA PerHandleData;
 DWORD SendBytes,RecvBytes;
 DWORD Flags;

 while(TRUE)
 {
  GetQueuedCompletionStatus(CompletionPort,
   &BytesTransferred,(LPDWORD)*PerHandleData,
   (LPOVERLAPPED *)&PerIoData,INFINITE);
  if(BytesTransferred == 0 &&
   (PerIoData->OperationType == RECV_POSTED ||
   PerIoData->OperationType == SEND_POSTED))
  {
   //socket has been closed by the peer
   closesocket(PerHandleData->Socket);
   GlobalFree(PerHandleData);
   GlobalFree(PerIoData);
   continue;
  }

  if(PerIoData->OperationType == RECV_POSTED)
  {
   //Do something with the received data
   //in PerIoData->Buffer
  }

  //Post another WSASend or WSARecv Operation.
  Flags = 0;
  ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
  PerIoData->DataBuf.len = DATA_BUFSIZE;
  PerIoData->DataBuf.buf = PerIoData->Buffer;
  PerIoData->OperationType = RECV_POSTED;

  WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1, &RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
 }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值