Last active
March 19, 2019 15:33
-
-
Save guodongxiaren/19a09c579294b5e6a32165f30e875d6a to your computer and use it in GitHub Desktop.
copy from iocp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
void IOCP_main() | |
{ | |
DWORD Ret; | |
WSADATA wsaData; | |
//WSAStartup 调用Socket前必须指定版本 | |
if ((Ret = WSAStartup(0x0202, &wsaData)) != 0) | |
{ | |
printf("WSAStartup failed with error %d\n", Ret); | |
return ; | |
} | |
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 = ::ntohs(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); | |
pPerHandle->nOperationType = OP_READ; | |
// 投递一个接收请求 | |
::CreateIoCompletionPort((HANDLE)pPerHandle->s, hCompletion, (ULONG_PTR)pPerHandle, 0); | |
OVERLAPPED *pol = (OVERLAPPED *)::GlobalAlloc(GPTR, sizeof(OVERLAPPED)); | |
WSABUF buf; | |
buf.buf = pPerHandle->buf; | |
buf.len = BUFFER_SIZE; | |
DWORD dwRecv; | |
DWORD dwFlags = 0; | |
::WSARecv(pPerHandle->s, &buf, 1, &dwRecv, &dwFlags, pol, NULL); | |
} | |
} | |
DWORD WINAPI ServerThread(LPVOID lpParam) | |
{ // 得到完成端口对象句柄 | |
HANDLE hCompletion = (HANDLE)lpParam; | |
DWORD dwTrans; | |
PPER_HANDLE_DATA pPerHandle; | |
OVERLAPPED *pOverlapped; | |
while(TRUE) | |
{ // 在关联到此完成端口的所有套节字上等待I/O完成 | |
BOOL bOK = ::GetQueuedCompletionStatus(hCompletion,&dwTrans, (PULONG_PTR)&pPerHandle, &pOverlapped, WSA_INFINITE); | |
if(!bOK) // 在此套节字上有错误发生 | |
{ | |
printf("SOCKET error!\n"); | |
::closesocket(pPerHandle->s); | |
::GlobalFree(pPerHandle); | |
::GlobalFree(pOverlapped); | |
continue; | |
} | |
if(dwTrans == 0 && // 套节字被对方关闭 | |
(pPerHandle->nOperationType == OP_READ || pPerHandle->nOperationType == OP_WRITE)) | |
{ | |
printf("SOCKET close!\n"); | |
::closesocket(pPerHandle->s); | |
::GlobalFree(pPerHandle); | |
::GlobalFree(pOverlapped); | |
continue; | |
} | |
switch(pPerHandle->nOperationType) // 通过per-I/O数据中的nOperationType域查看什么I/O请求完成了 | |
{ | |
case OP_READ: // 完成一个接收请求 | |
{ | |
printf("SOCKET recv\n"); | |
pPerHandle->buf[dwTrans] = '\0'; | |
printf("%s\n",pPerHandle-> buf); // 继续投递接收I/O请求 | |
WSABUF buf; | |
buf.buf = pPerHandle->buf ; | |
buf.len = BUFFER_SIZE; | |
pPerHandle->nOperationType = OP_READ; | |
DWORD nFlags = 0; | |
::WSARecv(pPerHandle->s, &buf, 1, &dwTrans, &nFlags, pOverlapped, NULL); | |
WSABUF Data; | |
Data.buf="sss"; | |
Data.len=3; | |
DWORD bFlag; | |
send(pPerHandle->s,"www",3,true); | |
//WSASend(pPerHandle->s,&Data,1,&bFlag,true,(LPWSAOVERLAPPED)hCompletion,NULL); | |
} | |
break; | |
case OP_WRITE: // 本例中没有投递这些类型的I/O请求 | |
case OP_ACCEPT: | |
break; | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment