IOCP模型TCP服務器

主線程建立監聽套接字,建立額外工做線程,關聯IOCP,負責等待和接受到來的鏈接。服務器

調用GetQueuedCompletionStatus函數,函數返回:socket

1 調用失敗函數

2 套接字被對方關閉spa

3 請求成功完成線程

程序首先定義per-handle per-IO的操做數據的結構類型code

#define BUFFER_SIZE 1024 typedef struct _PER_HANDLE_DATA{ SOCKET s; sockaddr_in addr; }PER_HANDLE_DATA,*PPER_HANDLE_DATA; typedef struct _PER_IO_DATA{ OVERLAPPED ol; char buf[BUFFER_SIZE]; int nOperationType; #define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3 }PER_IO_DATA,*PPER_IO_DATA;

主要過程:對象

1 主線程建立完成端口對象,建立工做線程處理完成端口對象中的事件blog

2 建立監聽套接字,開始監聽服務器端口事件

3 進入無限循環,處理到來的請求it

  1)調用accept函數等待接受未決的鏈接請求   2)建立一個per-handle數據   3)投遞一個接收請求

實現代碼:

void main() { int nPort = 4567; HANDLE hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE,0,0,0); ::CreateThread(NULL,0,ServerThread,(LPVOID)hCompletion,0,0); SOCKET sListen = ::socket(AF_INET,SOCK_STREAM,0); SOCKADDR_IN si; si.sin_family = AF_INET; si.sin_port = htons(nPort); si.sin_addr.S_un.S_addr = INADDR_ANY; ::bind(sListen,(sockaddr*)&si,sizeof(si)); ::listen(sListen,5); while(TRUE){ //等待接收未決的請求
 SOCKADDR_IN saRemote; int nRemoteLen = sizeof(saRemote); SOCKET sNew = ::accept(sListen,(sockaddr*)&saRemote,&nRemoteLen); //建立per-handle
        PPER_HANDLE_DATA pPerHandle = (PPER_HANDLE_DATA)::GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA)); pPerHandle->s = sNew; memcpy(&pPerHandle->addr,&saRemote,nRemoteLen); ::CreateIoCompletionPort((HANDLE)pPerHandle->s,hCompletion,(DWORD)pPerHandle,0); //投遞一個接收請求
        PPER_IO_DATA pPerIO = (PPER_IO_DATA)::GlobalAlloc(GPTR,sizeof(PER_IO_DATA)); pPerIO->nOperationType = OP_READ; WSABUF buf; buf.buf = pPerIO->buf; buf.len = BUFFER_SIZE; DWORD dwRecv; DWORD dwFlags = 0; ::WSARecv(pPerHandle->s,&buf,1,&dwRecv,&dwFlags,&pPerIO->ol,NULL);//接收投遞求
 } } DWORD WINAPI ServerThread(LPVOID lpParam{ HANDLE hCompletion = (HANDLE)lpParam; DWORD dwTrans; PPER_HANDLE_DATA pPerHandle; PPER_IO_DATA pPerIO; while(TRUE){ BOOL bOK = ::GetQueuedCompletionStatus(hCompletion,&dwTrans,(LPDWORD)&pPerHandle,(LPOVERLAPPED*)&pPerIO,WSA_INFINITE); if(!bOK) { ::closesocket(pPerHandle->s); ::GlobalFree(pPerHandle); ::GlobalFree(pPerIO); continue; } if(dwTrans == 0 && (pPerIO->nOperationType==OP_READ||pPerIO->nOperationType==OP_WRITE)) { ::closesocket(pPerHandle->s); ::GlobalFree(pPerHandle); ::GlobalFree(pPerIO); continue; } switch(pPerIO->nOperationType) { case OP_READ: { pPerIO->buf[dwTrans] = '\0'; printf(pPerIO->buf); WSABUF buf; buf.buf = pPerIO->buf; buf.len = BUFFER_SIZE; pPerIO->nOperationType = OP_READ; DWORD nFlags = 0; ::WSARecv(pPerHandle->s,&buf,1,&dwTrans,&nFlags,&pPerIO->ol,NULL); } break; case OP_WRITE: case OP_ACCEPT: break; } } return 0; }
相關文章
相關標籤/搜索