Make it Better
IOCP模型Demo
2016-9-29 StanWind
#include <winsock2.h>
#include <stdio.h>
#include <process.h>
#include <time.h>
#pragma comment(lib,"ws2_32")

#define DEFAULT_BUFLEN 1024

typedef struct
{
OVERLAPPED Overlapped;
WSABUF DataBuf;
CHAR Buffer[DEFAULT_BUFLEN];
DWORD BytesRECV;
}PER_IO_DATA,*LPPER_IO_DATA;

typedef struct
{
SOCKET Socket;
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
int main()
{
SOCKADDR_IN InternetAddr;
SOCKET ServerSocket = INVALID_SOCKET;
SOCKET AcceptSocket = INVALID_SOCKET;
HANDLE CompletionPort;
SYSTEM_INFO SystemInfo;
PER_HANDLE_DATA a;
PER_IO_DATA b;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_DATA PerIoData;
DWORD RecvBytes;
DWORD Flags;
DWORD ThreadID;
WSADATA wsaData;
DWORD Ret;
int iResult;

PerIoData = &b;
PerHandleData =&a;

if ((CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,8)) == NULL)
{
printf("CreateIoCompletionPort err!\n");
return -1;
}

GetSystemInfo(&SystemInfo);

for (int i=0;i<(SystemInfo.dwNumberOfProcessors)*2;i++)//创建工作线程循环
{
HANDLE ThreadHandle;
if ((ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,(LPVOID)&CompletionPort,0,&ThreadID)) == NULL)
{
printf("创建工作线程i 失败");
return -1;
}
CloseHandle(ThreadHandle);
}

if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
{
printf("初始化失败");
return -1;
}

ServerSocket = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

if (ServerSocket == INVALID_SOCKET)
{
printf("WSASocket() failed with error %d\n",WSAGetLastError());
return -1;
}

InternetAddr.sin_family = AF_INET;
InternetAddr.sin_addr.s_addr=htonl(INADDR_ANY);
InternetAddr.sin_port = htons(9000);
iResult = bind(ServerSocket,(PSOCKADDR)&InternetAddr,sizeof(InternetAddr));
if (iResult == SOCKET_ERROR)
{
printf("bind失败");
return -1;
}
if (listen(ServerSocket,5)==SOCKET_ERROR)
{
printf("listen失败");
}

printf("TCP server 开始");

sockaddr_in addrClient;
int addrClientlen = sizeof(sockaddr_in);

while (TRUE)
{
AcceptSocket = WSAAccept(ServerSocket,(sockaddr *)&addrClient,&addrClientlen,NULL,0);
if (AcceptSocket == SOCKET_ERROR)
{
printf("WSAAccept() 失败");
return -1;
}

//
PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(LPPER_HANDLE_DATA));
if (PerHandleData == NULL)
{
printf("GlobalAlloc 失败");
return -1;
}
PerHandleData->Socket =AcceptSocket;

if (CreateIoCompletionPort((HANDLE)AcceptSocket,CompletionPort,(DWORD)PerHandleData,0) == NULL)
{
printf("CreateIoCompletionPort 失败");
return -1;
}

PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
if (PerHandleData == NULL)
{
printf("GlobalAlloc 失败");
return -1;
}

ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
PerIoData->BytesRECV = (DWORD)0;
PerIoData->DataBuf.len = DEFAULT_BUFLEN;
PerIoData->DataBuf.buf = PerIoData->Buffer;
Flags = 0;

iResult = WSARecv(AcceptSocket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);

if (iResult == SOCKET_ERROR)
{
if (WSAGetLastError()!=ERROR_IO_PENDING)
{
printf("wsarecv 错误");
return -1;
}
}
}
return 0;
}

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
HANDLE CompletionPort = *(HANDLE*)CompletionPortID;
DWORD BytesTransferred;
LPPER_HANDLE_DATA PerHandleData;
LPPER_IO_DATA PerIoData;
DWORD RecvBytes;
DWORD Flags;
int iResult;

while(true)
{
if (GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&PerIoData,INFINITE) == 0)
{
printf("GetQueuedCompletionStatus 失败");
return 0;
}

if (BytesTransferred == 0)
{
printf("Closing socket %d\n",PerHandleData->Socket);

if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
{
printf("close err");
return 0;
}

GlobalFree(PerHandleData);
GlobalFree(PerIoData);
continue;
}

if (PerIoData->BytesRECV == 0)
{
PerIoData->BytesRECV = BytesTransferred;
}

printf("\nBytes received: %d\n",BytesTransferred);

PerIoData->BytesRECV = 0;
Flags = 0;
ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
PerIoData->DataBuf.len = DEFAULT_BUFLEN;
PerIoData->DataBuf.buf = PerIoData->Buffer;
iResult =WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
if (iResult == SOCKET_ERROR)
{
if (WSAGetLastError()!= ERROR_IO_PENDING)
{
printf("WSARecv err:%d",WSAGetLastError());
return 0;
}
}
printf("%s",PerIoData->DataBuf.buf);
return 0;
}
}
发表评论:
昵称

邮件地址 (选填)

个人主页 (选填)

内容