windows下简单的IOCP模型迭代回声服务器实例
2017-04-25 16:04
363 查看
#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; }
相关文章推荐
- 简单的使用 IOCP 模型的 TCP 服务器例子
- 一个简单的IOCP服务器实例
- Windows 上静态编译 Libevent 2.0.10 并实现一个简单 HTTP 服务器(图文并茂,还有实例下载)
- windows下简单配置squid反向代理服务器
- 多线程编程实例----服务器客户端简单通信
- 一个简单的IOCP(IO完成端口)服务器/客户端类(1/2)
- 一个简单的IOCP(IO完成端口)服务器/客户端类(2/2)
- winsock 完成端口 简单服务器模型
- Windows下NLB(分工作组与域环境)、服务器群集简单搭建
- C# 创建Windows 服务简单实例
- windows下简单配置squid反向代理服务器[转]
- Windows下NLB(分工作组与域环境)、服务器群集简单搭建 推荐
- 实例解析SOCKET编程模型-服务器
- Windows rsync服务器备份配置实例
- 一个简单而又灵活的IOCP模块——完成端口通讯服务器(IOCP Socket Server)设计(四)
- IOCP加Windows线程池打造高伸缩性高性能的服务器应用
- 为Windows应用创建简单的异步调用模式(附实例代码)
- Apache 服务器简单配置实例
- 最简单的Windows套接字(Socket)例子(源码,实例)
- 一个简单的IOCP(IO完成端口)服务器/客户端类(2/2)