完成端口模型服务器客户端基础WSACompletionPortServer



// ---------------------------------
// <span style="font-family: Arial, Helvetica, sans-serif;">服务器</span>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h>


#define PORT 8088
#define DATA_BUFSIZE 8192


typedef struct _IO_DATA
{
	OVERLAPPED overLapped;
	WSABUF wsaBuf;
	CHAR chBuffer[DATA_BUFSIZE];
	DWORD nBytesSend;
	DWORD nBytesRecv;
} IO_DATA, * P_IO_DATA;


typedef struct _HANDLE_DATA
{
	SOCKET Socket;
} HANDLE_DATA, * P_HANDLE_DATA;


DWORD WINAPI workThread(LPVOID pCompletionPortID);


int main()
{
	SOCKET sListen;
	SOCKET sAccept;
	HANDLE hCompletionPort;
	SYSTEM_INFO sysInfo;
	P_HANDLE_DATA pHandleData;
	P_IO_DATA pIoData;


	DWORD nByteRecv;
	DWORD nFlags;
	DWORD nThreadID;
	WSADATA wsaData;
	
	int nReturn = 0;
	nReturn = WSAStartup(0x0202, &wsaData); // 为使代码简洁 nReturn后不进行错误检查。。。


	// 创建一个完成端口   
	hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
	if ( NULL == hCompletionPort)
	{
		return 0;
	}
	
	// 根据CPU数量,创建一定数量的工作线程,并将完成端口传给线程
	GetSystemInfo(&sysInfo);
	for(int i = 0; i < (sysInfo.dwNumberOfProcessors * 2); i++)
	{
		HANDLE hThreadHandle;
		hThreadHandle = CreateThread(NULL, 0, workThread, hCompletionPort, 0, &nThreadID);
		CloseHandle(hThreadHandle);
	}


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


	SOCKADDR_IN addrListen;
	addrListen.sin_family = AF_INET;
	addrListen.sin_port = htons(PORT);
	addrListen.sin_addr.s_addr = htonl(INADDR_ANY);


	nReturn = bind(sListen, (PSOCKADDR) &addrListen, sizeof(addrListen));
	nReturn = listen(sListen, 5);


	printf("Service Start!\n");


	while(TRUE)
	{
		sAccept = WSAAccept(sListen, NULL, NULL, NULL, 0);


		pHandleData = (P_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(HANDLE_DATA))
		pHandleData->Socket = sAccept;


		// 将连接sAccept和完成端口关联
		if (NULL == CreateIoCompletionPort((HANDLE) sAccept, hCompletionPort, (DWORD) pHandleData, 0))
		{
			printf("CreateIoCompletionPort failed with error %d\n", GetLastError());
			return 0;
		}


		pIoData = (P_IO_DATA) GlobalAlloc(GPTR, sizeof(IO_DATA));
		ZeroMemory(&(pIoData->overLapped), sizeof(OVERLAPPED));
		pIoData->nBytesSend = 0;
		pIoData->nBytesRecv = 0;
		pIoData->wsaBuf.len = DATA_BUFSIZE;
		pIoData->wsaBuf.buf = pIoData->chBuffer;
		nFlags = 0;


		// 进行I/O操作
		if (SOCKET_ERROR == WSARecv(sAccept, &(pIoData->wsaBuf), 1, &nByteRecv, &nFlags,
			&(pIoData->overLapped), NULL))
		{
			if (WSAGetLastError() != ERROR_IO_PENDING)
			{
				printf("WSARecv() failed with error %d\n", WSAGetLastError());
				return 0;
			}
		}
	}
	return 0;
}




DWORD WINAPI workThread(LPVOID pCompletionPortID)
{
	HANDLE hCompletionPort = (HANDLE) pCompletionPortID;
	DWORD nByteTrans;
	P_HANDLE_DATA pHandleData;
	P_IO_DATA pIoData;
	DWORD nByteSend, nByteRecv;
	DWORD nFlags;


	while(TRUE)
	{
		// 依赖完成端口,接收有关I/O操作完成情况的通知 阻塞式,直到I/O操作成功或失败
		GetQueuedCompletionStatus(hCompletionPort, &nByteTrans,
			(LPDWORD)&pHandleData, (LPOVERLAPPED *) &pIoData, INFINITE);


		if (0 == nByteTrans)
		{
			printf("Closing socket %d\n", pHandleData->Socket);
			closesocket(pHandleData->Socket);
			GlobalFree(pHandleData);
			GlobalFree(pIoData);
			continue;
		}


		if(0 == (pIoData->nBytesRecv))
		{
			pIoData->nBytesRecv = nByteTrans;
			pIoData->nBytesSend = 0;
		}
		else
		{
			pIoData->nBytesSend += nByteTrans;
		}


		if ((pIoData->nBytesRecv) > (pIoData->nBytesSend))
		{
			ZeroMemory(&(pIoData->overLapped), sizeof(OVERLAPPED));
			pIoData->wsaBuf.buf = pIoData->chBuffer + pIoData->nBytesSend;
			pIoData->wsaBuf.len = pIoData->nBytesRecv - pIoData->nBytesSend;


			printf("Recv:%s\n", pIoData->wsaBuf.buf);


			if (SOCKET_ERROR == WSASend(pHandleData->Socket, &(pIoData->wsaBuf), 1, &nByteSend, 0,
				&(pIoData->overLapped), NULL))
			{
				if (ERROR_IO_PENDING != WSAGetLastError())
				{
					printf("WSASend() failed with error %d\n", WSAGetLastError());
					return 0;
				}
			}
		}
		else
		{
			nFlags = 0;
			pIoData->nBytesRecv = 0;
			ZeroMemory(&(pIoData->overLapped), sizeof(OVERLAPPED));
			pIoData->wsaBuf.len = DATA_BUFSIZE;
			pIoData->wsaBuf.buf = pIoData->chBuffer;


			if (SOCKET_ERROR == WSARecv(pHandleData->Socket, &(pIoData->wsaBuf), 1, &nByteRecv, &nFlags,
				&(pIoData->overLapped), NULL))
			{
				if (ERROR_IO_PENDING != WSAGetLastError())
				{
					printf("WSARecv() failed with error %d\n", WSAGetLastError());
					return 0;
				}
			}
		}
	}
}



完成端口模型服务器客户端基础WSACompletionPortServer_第1张图片




=====================================================================================================

客户端



#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <stdio.h>

#define  PORT 8088
#define BUF_SIZE 8192
int main()
{
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2), &wsaData);

	SOCKET sockConnect;
	sockConnect = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sockConnect)
	{
		return -1;
	}

	int nErrorCode = 0;
	int nMode;
	nErrorCode = ioctlsocket(sockConnect, FIONBIO, (u_long*)&nMode);
	if (SOCKET_ERROR == nErrorCode)
	{
		return -1;
	}
	sockaddr_in addrConnect;
	addrConnect.sin_family = AF_INET;
	addrConnect.sin_port = htons(PORT);
	addrConnect.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

	int nAddrLen = sizeof(sockaddr_in);

	while(true)
	{
		nErrorCode = connect(sockConnect, (sockaddr*)&addrConnect, nAddrLen);
		if (SOCKET_ERROR == nErrorCode)
		{
			nErrorCode = WSAGetLastError();
			if (WSAEWOULDBLOCK == nErrorCode || WSAEINVAL == nErrorCode)
			{
				Sleep(300);
				continue;// 继续连接
			}
			else if (WSAEISCONN == nErrorCode) // 连接成功
			{
				break;
			}
			else
			{
				printf("Connect Error! %ld", WSAGetLastError());
				closesocket(sockConnect);
				WSACleanup();
				return -1;
			}
		}
	}

	char chBuf[BUF_SIZE];
	printf("Client Started OK!\n");

	while(true)
	{
		while(true)
		{
			ZeroMemory(chBuf, BUF_SIZE);
			printf("This is Client Input:");
			gets(chBuf);

			nErrorCode = send(sockConnect, chBuf, BUF_SIZE, 0);
			if (SOCKET_ERROR == nErrorCode)
			{
				nErrorCode = WSAGetLastError();
				if (WSAEWOULDBLOCK == nErrorCode)
				{
					Sleep(800);
					continue;
				}
				else
				{
					printf("Send Eror! %ld", nErrorCode);
					closesocket(sockConnect);
					WSACleanup();
					return -1;
				}
			}
			break;
		}

		while(true)
		{
			ZeroMemory(chBuf, BUF_SIZE);
			nErrorCode = recv(sockConnect, chBuf, BUF_SIZE, 0);
			if (SOCKET_ERROR == nErrorCode)
			{
				nErrorCode = WSAGetLastError();
				if (WSAEWOULDBLOCK == nErrorCode)
				{
					Sleep(300);
					continue;
				}
				else if (WSAETIMEDOUT == nErrorCode || WSAENETDOWN == nErrorCode)
				{
					printf("Recv Error! %ld", nErrorCode);
					closesocket(sockConnect);
					WSACleanup();
					return -1;
				}
			}
			printf("Recv--:%s\n", chBuf);
			break;
		}
	}

	return 0;
}



你可能感兴趣的:(socket)