windows下简单的IOCP模型迭代回声服务器实例

#include<iostream>
#include<WinSock2.h>
#include<Windows.h>
#include<process.h>
#pragma comment(lib,"ws2_32.lib")
#define BUF_SIZE 100
#define READ  3
#define WRITE 5
using namespace std;
typedef struct {    //客户端信息
	SOCKET hclientSocket;
	SOCKADDR_IN clientAddr;
}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;
int k, l, m, n;
typedef struct {  
	OVERLAPPED overlapped;  //I/O缓冲和重叠I/O都会使用  事件对象有两种状态  signaled:完成IO  unsignaled: 未完成
	WSABUF wsaBuf;
	char buffer[BUF_SIZE];  //数据缓冲区
	int rwMode;    // 操作类型:读或写  
}PER_IO_DATA,*LPPER_IO_DATA;

unsigned WINAPI EchoThreadMain(LPVOID CompletionPortIO);
void main() {
	WSADATA wsadata;
	HANDLE hComPort;
	SYSTEM_INFO sysInfo;  
	LPPER_IO_DATA ioInfo;
	LPPER_HANDLE_DATA handleInfo;
	SOCKET serverSocket;
	SOCKADDR_IN serverAddr;
	unsigned int  i;
	DWORD recvBytes,flags = 0;
	
	if(WSAStartup(MAKEWORD(2, 2), &wsadata)!=0)
		cout<<"WSAStartup() error"<<endl;
	//创建cp对象(第二个参数为0,所以是新建的一个iocp),最后一个参数为0 创建和CPU核数相同的线程 返回NULL即为创建失败
	hComPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); 
	GetSystemInfo(&sysInfo);  //获取系统信息
	for (i = 0; i < sysInfo.dwNumberOfProcessors; i++) //根据核数创建线程并传递给cp对象句柄
	{        // 创建安全线程 
		_beginthreadex(NULL, 0 ,EchoThreadMain, (LPVOID)hComPort, 0, NULL);
	}
	//最后一个参数是:创建重叠IO非阻塞模式的TCP套接字
	serverSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);
	if (serverSocket == INVALID_SOCKET)
		cout << "socket()  error" << endl;

	memset(&serverAddr, 0, sizeof(serverAddr));
	serverAddr.sin_family = AF_INET;
	serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	serverAddr.sin_port = htons(8000);

	if (bind(serverSocket, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
		cout << "bind () error" << endl;

	listen(serverSocket, 5);
	cout << "服务器启动成功!" << endl;


	while (1) {
		SOCKET clientSocket;
		SOCKADDR_IN clientAddr;
		int addrLen = sizeof(clientAddr);
		clientSocket = accept(serverSocket, (SOCKADDR*)&clientAddr, &addrLen);
		if (clientSocket != INVALID_SOCKET) cout << "已有客户端连接:" << clientSocket << endl;

		handleInfo = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));//开辟地址创建客户信息句柄
		handleInfo->hclientSocket = clientSocket;   //将accep函数的客户端套接字赋给句柄
		memcpy(&(handleInfo->clientAddr), &clientAddr, addrLen);  //拷贝地址赋给句柄
		//将accept传来的客户套接字和客户端地址和已存在的cp对象绑定,最后一个参数为0表示允许和CPU核数相同的线程访问该函数
		CreateIoCompletionPort((HANDLE)clientSocket, hComPort, (DWORD)handleInfo, 0);
		ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));  //创建事件对象等捆绑信息的句柄
		memset((&ioInfo->overlapped), 0, sizeof(OVERLAPPED));  
		ioInfo->wsaBuf.len = BUF_SIZE;
		ioInfo->wsaBuf.buf = ioInfo->buffer;
		ioInfo->rwMode = READ;
		WSARecv(handleInfo->hclientSocket, &(ioInfo->wsaBuf),1, &recvBytes, &flags, &(ioInfo->overlapped), NULL);
	//参数:1重叠IO套接字 2保存接受信息的结构体数组 3第二个参数数组的长度     4保存接受消息大小的变量地址 5设置或读取传输特性的消息
	//        6事件对象的状态    7Routine函数地址
	}
}

unsigned WINAPI EchoThreadMain(LPVOID  pComPort)
{
	cout << "线程 NO.  " << GetCurrentThreadId() << endl;
	cout << "EchoThreadMain() 初始化" << endl;
	HANDLE hComPort = (HANDLE)pComPort;
	SOCKET sock;
	DWORD bytesTrans;
	LPPER_HANDLE_DATA handleInfo;
	LPPER_IO_DATA ioInfo;
	DWORD flags = 0;
	while (1) {
		//在操作队列中获取IO完成的客户端信息    为什么第四个参数是ioInfo?因为ioInfo的地址和它第一个成员变量overlapped的地址相同
		GetQueuedCompletionStatus(hComPort, &bytesTrans, (PULONG_PTR)&handleInfo,(LPOVERLAPPED*)&ioInfo, INFINITE);
		cout << "获取完队列的信息" << endl;
		cout << "客户端地址" << handleInfo->hclientSocket << endl;
		cout << "线程 NO.  " << GetCurrentThreadId() << endl;
		sock = handleInfo->hclientSocket;
		if (ioInfo->rwMode == READ) { //判断客户端是读还是写
			cout << "message received!" << endl;
			if (bytesTrans == 0) {  //传输EOF时
				closesocket(sock);
				free(handleInfo);
				free(ioInfo);
				cout << "客户端关闭:" << sock << endl;
				continue;
			}
			memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED)); //初始化时间对象的状态
			ioInfo->wsaBuf.len = bytesTrans;
			ioInfo->rwMode = WRITE; 
			//客户端socket 缓存数组地址  数组长度  保存实际字节数变量的地址  数据传输特性   时间状态  Routine函数
			WSASend(sock, &(ioInfo->wsaBuf), 1, NULL, 0, &(ioInfo->overlapped), NULL);
			cout << "发送完数据" << endl;
			ioInfo = (LPPER_IO_DATA)malloc(sizeof(PER_IO_DATA));
			memset(&(ioInfo->overlapped), 0, sizeof(OVERLAPPED));
			ioInfo->wsaBuf.len = BUF_SIZE;
			ioInfo->wsaBuf.buf = ioInfo->buffer;
			ioInfo->rwMode = READ;
			WSARecv(sock, &(ioInfo->wsaBuf), 1, NULL, &flags, &(ioInfo->overlapped), NULL);
			cout << "接受完数据" << endl;
		}
		else {
			cout << "message sent!" << endl;
			free(ioInfo);
		}
	}
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值