完成端口模型

  • CreateIoCompletionProt创建完成端口,参数为invalid_handle_value,null,0,0
  • 获取系统信息,创建几个线程,绑定到上述完成端口上,
  • 使用WSASocket创建socket
  • 监听
  • 主函数里监听连接事件,收到则用CreateIoCompletionProt将其绑定到完成端口上,并在其后为线程所用的数据开内存,因为线程重复执行,不方便在线程里面开内存
//#include<windows.h>
#include<iostream>
#include<winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;
typedef struct {
    
    
	OVERLAPPED Overlapped;
	WSABUF DataBuf;
	char Buffer[2048];
	DWORD BytesSEND;
	DWORD BytesRECV;

}PER_IO_OPERATION_DATA,*LPPER_IO_OPERATION_DATA;

typedef struct {
    
    
	SOCKET Socket;
}PER_HANDLE_DATA ,*LPPER_HANDLE_DATA;
DWORD WINAPI worker(LPVOID CompletionPortID) {
    
    
	HANDLE CompletionPort = (HANDLE)CompletionPortID;
	DWORD BytesTransferred;
	LPOVERLAPPED Overlapped;
	LPPER_HANDLE_DATA PerHandleData;
	DWORD Flags=0;
	LPPER_IO_OPERATION_DATA PerIoData;
	DWORD SendBytes, RecvBytes=0;
	while (true) {
    
    
		if (GetQueuedCompletionStatus(CompletionPort, &BytesTransferred
		,(LPDWORD)&PerHandleData,(LPOVERLAPPED*)&PerIoData,INFINITE)==0) {
    
    
			cout << "status error" << GetLastError() << endl;
			return 0;
		}

		if (BytesTransferred == 0) {
    
    //接收到的字节数
			cout << "closed socket %x" << PerHandleData->Socket << endl;
			closesocket(PerHandleData->Socket);
			GlobalFree(PerHandleData);
			GlobalFree(PerIoData);
			continue;
		}
		else {
    
    
			cout << PerIoData->Buffer << endl;
			PerIoData->BytesRECV = 0;
			Flags = 0;
			ZeroMemory(&(PerIoData->Overlapped), sizeof OVERLAPPED);
			PerIoData->DataBuf.len = 2048;
			PerIoData->DataBuf.buf = PerIoData->Buffer;
			ZeroMemory(PerIoData->Buffer, 2048);
			if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1,
				&RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) {
    
    
				if (WSAGetLastError() != ERROR_IO_PENDING) {
    
    
					cout<<"fatal error"<<endl;
					return 0;
				}
			}

			
		}
		

		
	}
}
int main() {
    
    
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
    
    
		cout << "wsastart faild<<endl" << endl;
		WSACleanup();
		return 1;
	};
	//创建完成端口
	HANDLE CompletionPort;
	SYSTEM_INFO SystemInfo;
	LPPER_HANDLE_DATA PerHandleData;
	LPPER_IO_OPERATION_DATA PerIoData;
	DWORD RecvBytes=0;
	DWORD Flags;
	DWORD ThreadID;
	if ((CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,
		NULL, 0, 0)) == NULL) {
    
    
		cout << "create Port failed"<<endl;
		return -1;
	}
	GetSystemInfo(&SystemInfo);
	for (int i = 0; i < SystemInfo.dwNumberOfProcessors; i++) {
    
    
		HANDLE ThreadHandle;
		if ((ThreadHandle = CreateThread(NULL, 0, worker, CompletionPort, 0, &ThreadID)) == NULL) {
    
    
			cout << "create thread failed " << endl;
			return -1;
		}
		CloseHandle(ThreadHandle);
	}



	SOCKET Listen;
	if ((Listen = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED)) == INVALID_SOCKET) {
    
    
		cout << "socket failed" << endl;
		return -2;
	}

	struct sockaddr_in addr;
	int addr_len = sizeof(sockaddr_in);
	int port = 9901;
	int errCode;
	//inet_addr(char *) ->ulong
	//inet_ntoa(in_addr in)->char
	//htons short
	//htonl long
	//ntohs short
	//
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	addr.sin_addr.s_addr = htonl(INADDR_ANY);
	errCode = bind(Listen, (SOCKADDR*)&addr, addr_len);
	if (errCode == SOCKET_ERROR) {
    
    
		cout << "bind failed" << endl;
		return 1;
	}

	if (listen(Listen, 5) == SOCKET_ERROR) {
    
    
		cout << "listen error" << endl;
		exit(2);
	}
	SOCKET Accept;
	while (1) {
    
    
		if ((Accept = WSAAccept(Listen, NULL, NULL, NULL, 0)) == SOCKET_ERROR) {
    
    
			cout << "accept error" << endl;
			return -3;
		}
		cout << "accept " << endl;
		if ((PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,
			sizeof PER_HANDLE_DATA)) == NULL) {
    
    
			cout<<"malloc failed"<<endl;
				return -4;
		}
		cout << "malloc success " << endl;
		PerHandleData->Socket = Accept;
		if (CreateIoCompletionPort((HANDLE)Accept, CompletionPort,
			(DWORD)PerHandleData, 0) == NULL) {
    
    
			cout << "bind port failed" << endl;
			return -4;
		}
		cout << "bind port success " << endl;

		if ((PerIoData = (LPPER_IO_OPERATION_DATA)GlobalAlloc(GPTR, sizeof(PER_IO_OPERATION_DATA))) == NULL) {
    
    
			cout<<"malloc failed 2"<<endl;
			return -3;
		}
		cout << "malloc success" << endl;
		ZeroMemory(PerIoData, sizeof PER_IO_OPERATION_DATA);
		Flags = 0;
		PerIoData->DataBuf.len = 2048;
		PerIoData->DataBuf.buf = PerIoData->Buffer;
		if (WSARecv(Accept, &(PerIoData->DataBuf), 1, &RecvBytes, &Flags, &(PerIoData->Overlapped), NULL) == SOCKET_ERROR) {
    
    
			if (WSAGetLastError() != ERROR_IO_PENDING) {
    
    
				cout << "recv error" << endl;
				return -3;
			}
		};
		
	}
	return 0;


}

猜你喜欢

转载自blog.csdn.net/weixin_39057744/article/details/120689867
今日推荐