完成端口(IOCP)--实例

本文介绍了如何使用完成端口(IOCP)并强调了一个关键的初始化步骤:memset(&pPer_IO_Data->overlapped,0,sizeof(pPer_IO_Data->overlapped))。作者通过分享自己的学习经历,指出这个步骤对于解决可能出现的问题至关重要,旨在帮助读者避免遇到同样的困扰。" 107407076,9242521,SpringBoot环境配置管理:多环境properties文件使用,"['Spring框架', '配置管理', '开发实践', '项目部署']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习的时候,在网上找了好久,但是都没找到满意的。自己会了,写一个可以运行的吧!

memset(&pPer_IO_Data->overlapped,0,sizeof(pPer_IO_Data->overlapped));
这一句非常重要,因为开始几次没有写这句话,老是出现问题,而且还找不到原因,查了好多的资料,总算是解决了!!

也希望大家能避免这个问题!

#include <WINSOCK2.H>
#include <windows.h>
#include <iostream>
#include <basetsd.h> 
using namespace std;

#pragma comment(lib,"ws2_32.lib")

#define BUFFER_SIZE 4096
#define PORT 12345


#define  OP_READ 1
#define  OP_WRITE 2
#define	 OP_ACCEPT 3

static int index=0;

HANDLE hCompletion;
typedef struct _PER_HANDLE_DATA
{
	SOCKET sock;
	sockaddr_in si;
}PER_HANDLE_DATA,*PPER_HANDLE_DATA;


typedef struct _PER_IO_DATA
{
	OVERLAPPED overlapped;
	WSABUF wsabuf;
	char buffer[BUFFER_SIZE];
	int operationType;
}PER_IO_DATA,*PPER_IO_DATA;
DWORD WINAPI ServerThread(LPVOID lParam);
int main()
{
	WSADATA wsa;
	WSAStartup(MAKEWORD(2,2),&wsa);
	
	
	hCompletion=::CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
	HANDLE h_DoThread=CreateThread(NULL,0,ServerThread,(LPVOID)hCompletion,0,0);
	
	SOCKET sListen=socket(AF_INET,SOCK_STREAM,0);
	sockaddr_in si;
	si.sin_family=AF_INET;
	si.sin_port=htons(PORT);
	si.sin_addr.S_un.S_addr=INADDR_ANY;
	bind(sListen,(SOCKADDR *)&si,sizeof(SOCKADDR));
	listen(sListen,5);
	
	while(TRUE)
	{
		sockaddr_in RemoteInfo;
		int RemoteLen=sizeof(sockaddr_in);
		SOCKET AcceptClient=accept(sListen,(sockaddr*)&RemoteInfo,&RemoteLen);
		//每当有新连接时,将为其创建PER_HANDLE_DATA数据和PER_IO_DATA数据。
		//PER_HANDLE_DATA
		PPER_HANDLE_DATA pPerHandleData=new PER_HANDLE_DATA();
		pPerHandleData->sock=AcceptClient;
		memcpy(&(pPerHandleData->si),&RemoteInfo,sizeof(sockaddr));
		//将套接字句柄与完成端口相关联
		CreateIoCompletionPort((HANDLE)pPerHandleData->sock,hCompletion,
			(DWORD)pPerHandleData,0);
		
		
		//PER_IO_DATA
		PPER_IO_DATA pPer_IO_Data=new PER_IO_DATA();
		pPer_IO_Data->operationType=OP_READ;
		//WSARecv等函数中,缓冲区必须是WSABUF,下面对WSABUF进行初始化

		pPer_IO_Data->wsabuf.buf=pPer_IO_Data->buffer;
		pPer_IO_Data->wsabuf.len=BUFFER_SIZE;
		DWORD dwRecv;
		DWORD dwFlags=0;

		//
		memset(&pPer_IO_Data->overlapped,0,sizeof(pPer_IO_Data->overlapped));
		//投递一个接收请求
		::WSARecv(pPerHandleData->sock,&(pPer_IO_Data->wsabuf),
			1,&dwRecv,&dwFlags,&(pPer_IO_Data->overlapped),NULL);
			
	}
	
	return 0;
}

DWORD WINAPI ServerThread(LPVOID lParam)
{
	
	HANDLE hCompletion=(HANDLE)lParam;
	DWORD dwTrans;
	PPER_HANDLE_DATA pPer_Handle_Data;
	PPER_IO_DATA pPer_IO_Data;
	cout<<"ServerThread"<<endl;
	while (TRUE)
	{
		
		bool bOk=GetQueuedCompletionStatus(hCompletion,&dwTrans,(LPDWORD)&pPer_Handle_Data,(LPOVERLAPPED*)&pPer_IO_Data,INFINITE);
		if(!bOk)
		{
			cout<<GetLastError()<<endl;
			//在此套接字上有错误发生
			closesocket(pPer_Handle_Data->sock);
			
			delete pPer_Handle_Data;
			delete pPer_IO_Data;
			continue;
		}
		
		//套接字被对方关闭
		if(dwTrans==0 && pPer_IO_Data->operationType==OP_READ || pPer_IO_Data->operationType==OP_WRITE )
		{
			closesocket(pPer_Handle_Data->sock);
			delete pPer_Handle_Data;
			delete pPer_IO_Data;
			continue;
		}
	
		
		switch(pPer_IO_Data->operationType)
		{
			cout<<"Switch"<<endl;
		case OP_READ:
			{

				pPer_IO_Data->buffer[dwTrans]='\0';
				cout<<pPer_IO_Data->buffer<<endl;
				index++;
				cout<<index<<endl;
				
				
				//继续投递IO操作
				WSABUF wsabuf;
				wsabuf.buf=pPer_IO_Data->buffer;
				wsabuf.len=BUFFER_SIZE;
				pPer_IO_Data->operationType=OP_READ;
				DWORD flags=0;
				WSARecv(pPer_Handle_Data->sock,&wsabuf,1,&dwTrans,&flags,&(pPer_IO_Data->overlapped),NULL);
				
			}
		case OP_WRITE:
			break;
		case OP_ACCEPT:
			break;
		}
	}
	return 0;
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值