IOCP模型Demo
首页 > 后端开发    作者:StanWind   2016年9月29日 9:42 星期四   热度:1052°   百度已收录  
时间:2016-9-29 9:42   热度:1052° 
#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;
	}
}
二维码加载中...
本文作者:StanWind      文章标题: IOCP模型Demo
本文地址:https://www.stanwind.com/post/16
版权声明:若无注明,本文皆为“Make it Better”原创,转载请保留文章出处。

返回顶部    首页    手机版本    后花园  
版权所有:Make it Better    站长: StanWind    赣ICP备17014296号   360网站安全检测平台  
00:00 / 00:00
随机播放