IOCP底层,支持超过15000个连接

#pragma comment(lib,"ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////
// 仅供测试软件用


#define DATA_BUFSIZE 1024        // 接收缓冲区大小
typedef enum{ IOSEND,IORECV,IOQUIT } IO_TYPE;
typedef struct _SOCKET_INFORMATION {
	OVERLAPPED Overlapped;
	SOCKET        Socket;
	IO_TYPE  IoType;
	char                buffer[DATA_BUFSIZE];
	WSABUF        DataBuf;
	DWORD        BytesSEND;
	DWORD        BytesRECV;
} SOCKET_INFORMATION, * LPSOCKET_INFORMATION;
DWORD   Flags = 0,
Bytes = 0;
DWORD WINAPI WorkThread(LPVOID CompletionPortID);
DWORD WINAPI AcceptThread(LPVOID lpParameter)
{
	WSADATA wsaData;
	HANDLE hCompPort;
	DWORD ThreadID;
	DWORD Ret;
	if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
	{
		printf("WSAStartup failed with error %d\n", Ret);
		return FALSE;
	}
	if ((hCompPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0)) == NULL)
	{
		printf( "CreateIoCompletionPort failed with error: %d\n", GetLastError());
		return FALSE;
	}
	// 根据CPU个数来创建线程,以达到最佳性能
	SYSTEM_INFO SystemInfo;
	GetSystemInfo(&SystemInfo);
	for(unsigned int i=0; i<SystemInfo.dwNumberOfProcessors*2; i++)
	{
		HANDLE ThreadHandle;
		if ((ThreadHandle = CreateThread(NULL, 0, WorkThread, hCompPort, 0, &ThreadID)) == NULL)
		{
			printf("CreateThread() failed with error %d\n", GetLastError());
			return FALSE;
		}
		CloseHandle(ThreadHandle);
	}
	SOCKET ListenSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, NULL, WSA_FLAG_OVERLAPPED);
	SOCKADDR_IN ServerAddr;
	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	ServerAddr.sin_port = htons(7999);
	bind(ListenSocket,(LPSOCKADDR)&ServerAddr,sizeof(ServerAddr));
	listen(ListenSocket,100);
	printf("listenning...\n");
	SOCKADDR_IN ClientAddr;
	int addr_length=sizeof(ClientAddr);
	while (TRUE)
	{
		LPSOCKET_INFORMATION  SI = new SOCKET_INFORMATION;
		if ((SI->Socket = accept(ListenSocket,(SOCKADDR*)&ClientAddr, &addr_length)) != INVALID_SOCKET)
		{
			printf("accept ip:%s port:%d\n",inet_ntoa(ClientAddr.sin_addr),ClientAddr.sin_port);
			// 相关参数初始化
			memset(&SI->Overlapped,0,sizeof(WSAOVERLAPPED));
			memset(SI->buffer, 0, DATA_BUFSIZE);
			SI->DataBuf.buf = SI->buffer;
			SI->DataBuf.len = DATA_BUFSIZE;
			SI->BytesRECV        = 0;
			SI->BytesSEND        = 0;
			SI->IoType           = IORECV;


			if (CreateIoCompletionPort((HANDLE)SI->Socket, hCompPort, (DWORD)SI, 0) == NULL)
			{
				printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
				return FALSE;
			}
			// 发出一个重叠I\O请求
			if(WSARecv(SI->Socket, &SI->DataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
			{
				if(WSAGetLastError() != WSA_IO_PENDING)
				{
					printf("disconnect\n");
					closesocket(SI->Socket); 
					delete SI;
					continue;
				}
			}
		}


	}
	return FALSE;
}
DWORD WINAPI WorkThread(LPVOID CompletionPortID)
{
	HANDLE hCompPort = (HANDLE)CompletionPortID;
	while (TRUE)
	{
		DWORD BytesTransferred = 0;
		LPSOCKET_INFORMATION SI = NULL;
		LPWSAOVERLAPPED Overlapped = NULL;
		// 线程进入线程池,等待被唤醒
		if (GetQueuedCompletionStatus(hCompPort, &BytesTransferred, (LPDWORD)&SI, &Overlapped, INFINITE))
		{
			if (0 == BytesTransferred && IOQUIT != SI->IoType)
			{
				printf("disconnect\n");
				closesocket(SI->Socket); 
				delete SI;
				continue;
			}
			switch(SI->IoType)
			{
			case IORECV:
				{
					printf("%s \n", SI->buffer);
					// 目前的功能是将接收到的数据原封不动的返回
					SI->DataBuf.len = BytesTransferred;
					SI->BytesRECV = BytesTransferred;
					SI->IoType = IOSEND;
					if (WSASend(SI->Socket, &SI->DataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
					{
						if(WSAGetLastError() != WSA_IO_PENDING)
						{
							printf("disconnect\n");
							closesocket(SI->Socket); 
							delete SI;
							continue;
						}
					}
					break;
				}
			case IOSEND:
				{
					SI->BytesSEND += BytesTransferred;


					//返回是否彻底,若未发完,接着发
					if (SI->BytesSEND < SI->BytesRECV)
					{
						SI->DataBuf.buf += BytesTransferred; 
						SI->DataBuf.len -= BytesTransferred; 
						SI->IoType = IOSEND;
						if (WSASend(SI->Socket, &SI->DataBuf, 1, &Bytes, Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
						{
							if(WSAGetLastError() != WSA_IO_PENDING)
							{
								printf("disconnect\n");
								closesocket(SI->Socket); 
								delete SI;
								continue;
							}
						}
					}
					else if (SI->BytesSEND > SI->BytesRECV)
					{
						printf("BytesSEND:%d > BytesRECV:%d\n",SI->BytesSEND,SI->BytesRECV);
						memset(SI->buffer, 0, DATA_BUFSIZE);
						SI->BytesRECV = 0;
						SI->BytesSEND = 0;


						SI->IoType = IORECV;
						SI->DataBuf.len = DATA_BUFSIZE;
						SI->DataBuf.buf = SI->buffer;
					}
					else
					{
						memset(SI->buffer, 0, DATA_BUFSIZE);
						SI->BytesRECV = 0;
						SI->BytesSEND = 0;
						SI->IoType = IORECV;
						SI->DataBuf.len = DATA_BUFSIZE;
						SI->DataBuf.buf = SI->buffer;
						if (WSARecv(SI->Socket, &SI->DataBuf, 1, &Bytes, &Flags, &SI->Overlapped, NULL) == SOCKET_ERROR)
						{
							if(WSAGetLastError() != WSA_IO_PENDING)
							{
								printf("disconnect\n");
								closesocket(SI->Socket); 
								delete SI;
								continue;
							}
						}
					}
					break;
				}


			case IOQUIT:
				{
					// 让线程安全退出
					return FALSE;
					break;
				}


			default:
				break;
			}
		}        
	}        
	return FALSE;
}
void main()   
{
	HANDLE hThreads = CreateThread(NULL, 0, AcceptThread, NULL, NULL, NULL); 


	WaitForSingleObject(hThreads,INFINITE);
	printf("exit\n");
	CloseHandle(hThreads);
} 


你可能感兴趣的:(IOCP底层,支持超过15000个连接)