要详细:
#include <stdio.h>
#include <winsock2.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#define LISTEN_PORT 8080
#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;
DWORD WINAPI ServerThread(LPVOID lpParam)
{
DWORD dwTrans = 0;
DWORD dwFlags = 0;
HANDLE hCompletion = (HANDLE)lpParam;
PPER_IO_DATA pPerIo = NULL;
PPER_HANDLE_DATA pPerHandle = NULL;
while (true)
{
BOOL bOK;
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);
}
switch (pPerIo->nOperationType)
{
case OP_READ:
{
pPerIo->buf[dwTrans] = '\0';
printf(pPerIo->buf);
WSABUF WSABuf;
WSABuf.buf = pPerIo->buf;
WSABuf.len = BUFFER_SIZE;
pPerIo->nOperationType = OP_READ;
::WSARecv(pPerHandle->s, &WSABuf, 1, &dwTrans, &dwFlags, &pPerIo->ol, NULL);
break;
}
case OP_WRITE:
break;
case OP_ACCEPT:
break;
}
}
return 0;
}
int main()
{
WSADATA WSAData;
WORD wVersion = MAKEWORd(2, 2);
SOCKET sListen = 0;
SOCKET sAccept = 0;
HANDLE hCompletion = 0;
hCompletion = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
::CreateThread(NULL, 0, ServerThread, (LPVOID)hCompletion, 0, 0);
if (::WSAStartup(wVersion, &WSAData) != 0)
{
::WSACleanup();
return -1;
}
sListen = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sListen == INVALID_SOCKET)
{
::closesocket(sListen);
return -2;
}
sockaddr_in TCP;
TCP.sin_family = AF_INET;
TCP.sin_port = htons(LISTEN_PORT);
TCP.sin_addr.S_un.S_addr = INADDR_ANY;
if (::bind(sListen, (sockaddr*)&TCP, sizeof(TCP)) == SOCKET_ERROR)
{
::closesocket(sListen);
return -3;
}
if (::listen(sListen, 5) == SOCKET_ERROR)
{
::closesocket(sListen);
return -4;
}
while (true)
{
sockaddr_in remote;
int nLen = sizeof(remote);
SOCKET sThread = ::accept(sListen, (sockaddr*)&remote, &nLen);
PPER_HANDLE_DATA pPerHandle = (PPER_HANDLE_DATA)::GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA));
pPerHandle->s = sThread;
memcpy(&pPerHandle->addr, &remote, nLen);
::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 = 0;
DWORD dwFlags = 0;
::WSARecv(pPerHandle->s, &buf, 1, &dwRecv, &dwFlags, &pPerIo->ol, NULL);
}
return 0;
}
再问下,如何学习iocp模型?