iocp 完成端口模型

2 篇文章 0 订阅
1 篇文章 0 订阅
// my_iocp.cpp
#include <WinSock2.h>
#include <process.h>
#include <iostream>
using namespace std;

#pragma comment (lib, "ws2_32")

typedef struct  
{
	SOCKET socket;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;

const int DATA_BUF_SIZE = 9000;

typedef struct  
{
	OVERLAPPED overlapped;
	WSABUF dataBuf;
	char buf[DATA_BUF_SIZE];
	DWORD dwSend;
	DWORD dwRecv;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;

unsigned __stdcall SerWorkThread(void *param);

const char IP[] = "127.0.0.1";
const unsigned short PORT = 5150;


int main()
{
	SOCKET fdSock = INVALID_SOCKET;
	sockaddr_in serAddr = {0};

	HANDLE hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 0);
	if (hIocp == NULL)
	{
		cout << "CreateIoCompletionPort error " << GetLastError() << endl;
		return -1;
	}

	SYSTEM_INFO sysInfo = {0};
	GetSystemInfo(&sysInfo);

	for (unsigned int i = 0; i < sysInfo.dwNumberOfProcessors; i++)
	{
		unsigned int uiThreadId = 0;
		HANDLE handle = (HANDLE)_beginthreadex(NULL, 0, SerWorkThread, hIocp, 0, &uiThreadId);
		if (handle == NULL)
		{
			return -1;
		}

		CloseHandle(handle);
	}

	WSAData	wsaData = {0};
	WSAStartup(0x0202, &wsaData);
	if (wsaData.wVersion != 0x0202)
	{
		cout << "not support socket 0x0202 lib." << endl;
		goto clear;
	}

	fdSock = socket(AF_INET, SOCK_STREAM, 0);
	if (fdSock == INVALID_SOCKET)
	{
		goto clear;
	}

	serAddr.sin_family = PF_INET;
	serAddr.sin_addr.s_addr = inet_addr(IP);
	serAddr.sin_port = htons(PORT);

	if (SOCKET_ERROR == bind(fdSock, reinterpret_cast<sockaddr *>(&serAddr), sizeof(sockaddr_in)))
	{
		goto clear;
	}

	if (SOCKET_ERROR == listen(fdSock, 10))
	{
		goto clear;
	}

	while (true)
	{
		LPPER_HANDLE_DATA pPerHandleData = NULL;
		LPPER_IO_OPERATION_DATA pPerIoData = NULL;
		DWORD dwFlag = 0;
		DWORD dwRecved = 0;

		sockaddr_in cliAddr = {0};
		int iAddrlen = sizeof(sockaddr_in);
		SOCKET cliSock = accept(fdSock, reinterpret_cast<sockaddr*>(&cliAddr), &iAddrlen);
		if (INVALID_SOCKET == cliSock)
		{
			cout << "accept error code " << WSAGetLastError() << endl;
			goto clear;
		}

		pPerHandleData = new PER_HANDLE_DATA;
		pPerHandleData->socket = cliSock;

		if (NULL == CreateIoCompletionPort(reinterpret_cast<HANDLE>(cliSock), hIocp, reinterpret_cast<ULONG_PTR>(pPerHandleData), 0))
		{
			goto clear;
		}

		pPerIoData = new PER_IO_OPERATION_DATA;
		memset(pPerIoData, 0, sizeof(PER_IO_OPERATION_DATA));
		pPerIoData->dwRecv = 0;
		pPerIoData->dwSend = 0;
		pPerIoData->dataBuf.buf = pPerIoData->buf;
		pPerIoData->dataBuf.len = DATA_BUF_SIZE;

		if (SOCKET_ERROR == WSARecv(cliSock, &pPerIoData->dataBuf, 1, &dwRecved, &dwFlag, &pPerIoData->overlapped, NULL))
		{
			if (WSAGetLastError() != WSA_IO_PENDING)
			{
				cout << "WSARecv error code: " << WSAGetLastError() << endl;
				goto clear;
			}
		}

		//memset(&pPerIoData->overlapped, 0, sizeof(pPerIoData->overlapped));
		//pPerIoData->dataBuf.len = sizeof("hello world!");
		//pPerIoData->dataBuf.buf = pPerIoData->buf;
		//strcpy_s(pPerIoData->buf, DATA_BUF_SIZE, "hello world!");

		//if (SOCKET_ERROR == WSASend(cliSock, &pPerIoData->dataBuf, 1, &dwRecved, 0, &pPerIoData->overlapped, NULL))
		//{
		//	if (WSAGetLastError() != WSA_IO_PENDING)
		//	{
		//		cout << "WSARecv error " << WSAGetLastError() << endl;
		//		return 0;
		//	}
		//}

		cout << "client " << cliSock << " connected." << endl;
	}

clear:
	WSACleanup();
	if (fdSock != INVALID_SOCKET)
	{
		closesocket(fdSock);
		fdSock = INVALID_SOCKET;
	}
	return 0;
}

unsigned __stdcall SerWorkThread(void *param)
{
	if (param == NULL)
	{
		return 0;
	}

	DWORD dwFlag = 0;
	DWORD dwRecved = 0;
	DWORD dwBytesTransferred = 0;
	LPPER_HANDLE_DATA pPerHandle = NULL;
	LPPER_IO_OPERATION_DATA pPerIoData = NULL;

	HANDLE hIocp = reinterpret_cast<HANDLE>(param);

	while (true)
	{
		dwBytesTransferred = 0;
		if (FALSE == GetQueuedCompletionStatus(hIocp, &dwBytesTransferred, reinterpret_cast<PULONG_PTR>(&pPerHandle), reinterpret_cast<LPOVERLAPPED*>(&pPerIoData), INFINITE))
		{
			cout << "GetQueuedCompletionStatus error " << WSAGetLastError() << endl;

			if (pPerHandle != NULL)
			{
				closesocket(pPerHandle->socket);
				delete pPerHandle;
				pPerHandle = NULL;
			}

			if (pPerIoData != NULL)
			{
				delete	pPerIoData;
				pPerIoData = NULL;
			}

			continue;
		}

		if (dwBytesTransferred == 0)
		{
			cout << "disconnect from client " << pPerHandle->socket << "." << endl;

			if (pPerHandle != NULL)
			{
				closesocket(pPerHandle->socket);
				delete pPerHandle;
				pPerHandle = NULL;
			}

			if (pPerIoData != NULL)
			{
				delete	pPerIoData;
				pPerIoData = NULL;
			}

			continue;
		}
		else
		{
			if (pPerIoData == NULL || pPerHandle == NULL)
			{
				return 0;
			}

			cout  << pPerHandle->socket << " len :" << dwBytesTransferred <<  " recv : " << pPerIoData->dataBuf.buf << endl;

			dwFlag = 0;
			memset(&pPerIoData->overlapped, 0, sizeof(pPerIoData->overlapped));
			pPerIoData->dataBuf.buf = pPerIoData->buf;
			pPerIoData->dataBuf.len = DATA_BUF_SIZE;

			if (SOCKET_ERROR == WSARecv(pPerHandle->socket, &pPerIoData->dataBuf, 1, &dwRecved, &dwFlag, &pPerIoData->overlapped, NULL))
			{
				if (WSAGetLastError() != WSA_IO_PENDING)
				{
					cout << "WSARecv error " << WSAGetLastError() << endl;

					if (pPerHandle != NULL)
					{
						closesocket(pPerHandle->socket);
						delete pPerHandle;
						pPerHandle = NULL;
					}

					if (pPerIoData != NULL)
					{
						delete	pPerIoData;
						pPerIoData = NULL;
					}

					continue;;
				}
			}

			//memset(&pPerIoData->overlapped, 0, sizeof(pPerIoData->overlapped));
			//pPerIoData->dataBuf.len = dwBytesTransferred;
			//pPerIoData->dataBuf.buf = pPerIoData->buf;
			//strcpy_s(pPerIoData->buf, DATA_BUF_SIZE, "hello world!");

			//if (SOCKET_ERROR == WSASend(pPerHandle->socket, &pPerIoData->dataBuf, 1, &dwRecved, 0, &pPerIoData->overlapped, NULL))
			//{
			//	if (WSAGetLastError() != WSA_IO_PENDING)
			//	{
			//		cout << "WSARecv error " << WSAGetLastError() << endl;
			//		continue;
			//	}
			//}

			memset(pPerIoData->dataBuf.buf, 0, pPerIoData->dataBuf.len);
		}
	}

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值