当前位置: 首页 > news >正文

[C++ 网络协议] IOCP(Input Output Completion Port)

1.什么是IOCP

IOCP(Input Output Completion Port)输入输出完成端口。其实就是基于重叠I/O的一种改进的模型。

重叠I/O具有缺点:重复调用非阻塞模式的accpet函数和以进入alertablewait状态为目的的SleepEx函数会影响程序性能

而IOCP提供的解决方案便是:让主线程调用accept函数,单独创建至少一个线程来负责所有I/O的前后处理

但请不要过分关注在线程上,主要还是如下问题:

        1.I/O是否以非阻塞模式工作?

        2.如何确定非阻塞模式的I/O是否完成?

2.分阶段实现IOCP程序

2.1 实现原理

IOCP会将已完成的I/O信息注册到CP对象(Completion Port完成端口),而我们就可以通过CP对象来获取I/O是否完成的信息,所以有下面两项工作:

  • 创建完成端口对象
  • 建立完成端口对象和套接字之间的联系 

此时的套接字必须赋予重叠属性。

2.2 创建CP对象

#include<windows.h>HANDLE CreateIoCompletionPort(
HANDLE fileHandle,                //创建CP对象时传递INVALID_HANDLE_VALUE
HANDLE ExistingCompletionPort,    //创建CP对象时传递NULL
ULONG_PTR CompletionKey,          //创建CP对象时传递0
DWORD NumberOfConcurrentThreads   //分配给CP对象的用于处理I/O的线程数。//例如:该参数为2时,说明分配给CP对象的可以同时运行的线程数最多为2个//如果为0时,那么系统中CPU的个数就是可同时运行的最大线程数
);
成功返回CP对象句柄
失败返回NULL

2.3 创建和套接字连接完成的端口对象

#include<windows.h>HANDLE CreateIoCompletionPort(
HANDLE FileHandle,                //要连接到CP对象的套接字句柄
HANDLE ExistingCompletionPort,    //要连接套接字的CP对象句柄
ULONG_PTR CompletionKey,          //传递已完成I/O相关信息
DWORD NumberOfConcurrentThreads   //无论传递何值,只要第二个参数非NULL就会被忽略
);
成功返回CP对象句柄
失败返回NULL

函数功能:将FileHandle句柄指向的套接字和ExistingCompletionPort指向的CP对象相连。

调用此函数后:只要针对FileHandle的I/O完成,相关信息就会注册到ExistingCompletionPort里。

注意:第三个参数“传递已完成I/O相关信息”的意思是,你可以像重叠I/O里使用Complition routine来确认I/O方式里把相关信息填写到hEvent里的那样,写入其他信息,这样当I/O完成就可以获取了。

2.4 确认完成端口已完成的I/O和线程I/O处理

#include<windows.h>BOOL GetQueuedCompletionStatus(
HANDLE CompletionPort,        //注册有已完成I/O信息的CP对象句柄
LPDWORD lpNumberOfBytes,      //保存I/O过程中传输的数据大小的变量地址值
PULONG_PTR lpCompletionKey,   //保存CreateIoCompleytionPort函数第三个参数值得变量地址值
LPOVERLAPPED* lpOverlapped,   //保存调用WSASend、WSARecv函数时传递的OVERLAPPED结构体地址的变量地址值
DWORD dwMilliseconds          //超时信息,超过该指定时间后将返回FALSE并跳出函数。//传递INFINITE时,程序将阻塞,直到已完成I/O信息写入CP对象
);
成功返回TRUE
失败返回FALSE

注意:

  • 调用此函数的线程数量不能超过CreateIoCompletionPort时指定的线程数。
  • 此函数并不知道当前是输入信息状态还是输出信息状态,需要自行判断。

3. 实现IOCP模型的回声服务器端

思路:每连接一个客户端就创建一个线程,然后主线程里先接收一次数据,在子线程里通过GetQueuedCompletionStatus函数阻塞住线程,判断I/O状态,接着把接收的数据发送给客户端,再次进入接收状态,如此循环通信。

变量:

struct ClientInfo结构体:存有套接字和套接字地址族信息,在CreateIoCompletionPort函数里,建立套接字和CP的连接的时候,当做第三参数传入

struct CPInfo结构体:存有一个OVERLAPPED、WSABUF信息,以及还有一个int型用来判断当前是RECV还是SEND,在执行WSARecv函数时当做第六个参数进行传入。运用下面的知识点,所以可以在子线程执行GetQueuedCompletionStatus函数时,取得的第一个成员的地址,也就是这整个结构体的地址。

知识点:结构体变量地址值与结构体第一个成员的地址值相同。

struct CPInfo
{OVERLAPPED overlapped;WSABUF wsabuf;int mode;			//0:RECV 1:SEND
};
CPInfo data;
if(&data==&data.overlapped)
{std::cout<<"TRUE"<<std::endl;
}
else
{std::cout<<"FALSE"<<std::endl;
}
输出TRUE
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<WinSock2.h>
#include<process.h>
#include<Windows.h>
#include<malloc.h>
#include<string>struct ClientInfo
{SOCKET socket;sockaddr_in socketAddr;
};struct CPInfo
{OVERLAPPED overlapped;WSABUF wsabuf;int mode;			//0:RECV 1:SEND
};unsigned WINAPI threadClient(void* arg);int main()
{WSADATA wsaData;if (0 != WSAStartup(MAKEWORD(2, 2), &wsaData)){std::cout << "start up fail!" << std::endl;return 0;}SOCKET server = WSASocket(PF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);if (server == INVALID_SOCKET){std::cout << "socket fail!" << std::endl;return 0;}int mode = 1;ioctlsocket(server, FIONBIO, (u_long*)&mode);sockaddr_in serverAddr;memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);serverAddr.sin_port = htons(9130);if (SOCKET_ERROR == bind(server, (sockaddr*)&serverAddr, sizeof(serverAddr))){std::cout << "bind fail!" << std::endl;return 0;}if (SOCKET_ERROR == listen(server, 2)){std::cout << "listen fail!" << std::endl;return 0;}while (true){sockaddr_in clientAddr;memset(&clientAddr, 0, sizeof(clientAddr));int clientAddrLen = sizeof(clientAddr);SOCKET client = accept(server, (sockaddr*)&clientAddr, &clientAddrLen);if (client == SOCKET_ERROR){if (WSAGetLastError() == WSAEWOULDBLOCK)	//说明此时没有客户端连接{continue;}std::cout << "accept fail!" << std::endl;}else{HANDLE cpObject = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);if (cpObject == NULL){std::cout << "Create CP fail!" << std::endl;continue;}ClientInfo* clientinfo = new ClientInfo();clientinfo->socket = client;clientinfo->socketAddr = clientAddr;CreateIoCompletionPort((HANDLE)client, cpObject, (ULONG_PTR)clientinfo, 0);unsigned threadId;if (0 == _beginthreadex(NULL, 0, threadClient, (void*)&cpObject, 0, &threadId))	//创建一个线程{std::cout << "thread create fail!" << std::endl;continue;}CPInfo* cpinfo = new CPInfo();cpinfo->mode = 0;memset(&cpinfo->overlapped, 0, sizeof(cpinfo->overlapped));char buff[1024];cpinfo->wsabuf.buf = buff;cpinfo->wsabuf.len = sizeof(buff);DWORD readLen;DWORD flag = 0;WSARecv(client, &cpinfo->wsabuf, 1, &readLen, &flag, &cpinfo->overlapped, NULL);}}closesocket(server);WSACleanup();
}unsigned WINAPI threadClient(void* arg)
{HANDLE cpObject = *(HANDLE*)arg;CPInfo* cpinfo;ClientInfo* clientinfo;while (true){DWORD readLen;GetQueuedCompletionStatus(cpObject, &readLen, (PULONG_PTR)&clientinfo, (LPOVERLAPPED*)&cpinfo, INFINITE);if (readLen == 0){std::cout << "客户端:" << inet_ntoa(clientinfo->socketAddr.sin_addr) << "断开连接!" << std::endl;break;}if (cpinfo->mode == 0)		//recv{std::cout << "客户端发来的消息:" << cpinfo->wsabuf.buf << std::endl;DWORD flag = 0;cpinfo->mode = 1;WSASend(clientinfo->socket, &cpinfo->wsabuf, 1, &readLen, flag, &cpinfo->overlapped, NULL);CPInfo* cpinfo2 = new CPInfo();cpinfo2->mode = 0;memset(&cpinfo2->overlapped, 0, sizeof(cpinfo2->overlapped));char buff[1024];cpinfo2->wsabuf.buf = buff;cpinfo2->wsabuf.len = sizeof(buff);DWORD readLen2;WSARecv(clientinfo->socket, &cpinfo2->wsabuf, 1, &readLen2, &flag, &cpinfo2->overlapped, NULL);}else						//send{delete cpinfo;}}CloseHandle(cpObject);closesocket(clientinfo->socket);return 0;
}

相关文章:

[C++ 网络协议] IOCP(Input Output Completion Port)

1.什么是IOCP IOCP&#xff08;Input Output Completion Port&#xff09;输入输出完成端口。其实就是基于重叠I/O的一种改进的模型。 重叠I/O具有缺点&#xff1a;重复调用非阻塞模式的accpet函数和以进入alertablewait状态为目的的SleepEx函数会影响程序性能。 而IOCP提供…...

R实现地图相关图形绘制

大家好&#xff0c;我是带我去滑雪&#xff01; 地图相关图形绘制具有许多优点&#xff0c;这些优点使其在各种领域和应用中非常有用。例如&#xff1a;地图相关图形提供了一种直观的方式来可视化数据&#xff0c;使数据更容易理解和分析。通过地图&#xff0c;可以看到数据的空…...

【Jmeter】性能测试脚本开发——性能测试环境准备、Jmeter脚本编写和执行

文章目录 一、常用的Jmeter元件二、性能测试环境准备三、编写Jmeter脚本四、执行测试脚本 一、常用的Jmeter元件 取样器-HTTP请求 作用&#xff1a;发送HTTP请求配置原件-HTTP请求默认值 作用&#xff1a;设置HTTP请求的默认参数配置原件-用户定义的变量 作用&#xff1a;定义…...

看好你家电视盒的后门!数千个Android电视盒感染了与欺诈相关的危险恶意软件

如果你从Android电视盒获得流媒体修复程序&#xff0c;则你的设备可能会被恶意软件所感染&#xff0c;这些恶意软件能够进行广告欺诈、创建假帐户&#xff0c;并通过悄悄地将你的数据转移到中国的服务器来销售对家庭网络的访问。 根据本周的一份新报告&#xff0c;网络安全公司…...

LeetCode 1251. 平均售价

题目链接&#xff1a;1251. 平均售价 题目描述 表&#xff1a;Prices Column NameTypeproduct_idintstart_datedateend_datedatepriceint (product_id&#xff0c;start_date&#xff0c;end_date) 是 prices 表的主键&#xff08;具有唯一值的列的组合&#xff09;。 price…...

TypeScript 笔记:String 字符串

1 对象属性 length 返回字符串的长度 2 对象方法 charAt() 返回在指定位置的字符 charCodeAt() 返回在指定的位置的字符的 Unicode 编码 concat 连接两个或更多的字符串 indexOf 返回某个指定的字符串值在字符串中首次出现的位置 lastIndexOf 从后向前搜索字符串&…...

蓝牙技术|Matter或能改变中国智能家居市场,蓝牙技术将得到进一步应用

近年来&#xff0c;智能家居开放协议标准Matter&#xff08;目前版本 1.1&#xff09;由连接标准联盟发布&#xff0c;该联盟是一个由数百家公司组成的全球性机构&#xff0c;旨在提供与物联网 (IoT) 相关的标准。例如&#xff0c;Matter 用于允许 Amazon Alexa、Apple Home、G…...

VB.NET vs. VB6.0:现代化编程语言 VS 经典老旧语言

目录 ​.NET背景&#xff1a; 特点: VB6.0背景&#xff1a; 特点: 两者之间的不同: 总结: 升华: .NET背景&#xff1a; VB.NET一种简单&#xff0c;现代&#xff0c;面向对象计算机编程语言&#xff0c;有微软开发&#xff0c;VB.NET是一种基于.NET Framework的面向对象…...

ViewPager、RecycleView实现轮播图

1.ViewPager实现轮播图形效果。 1&#xff09;layout中&#xff0c;PageIndicatorView轮播的View <RelativeLayoutandroid:layout_width"match_parent"android:layout_height"200dp"android:orientation"vertical"><androidx.viewpager…...

【FreeRTOS】【STM32】01从零开始的freertos之旅 浏览源码下的文件夹

基于野火以及正点原子 在打开正点原子的资料pdf时&#xff0c;我遇到了pdf无法复制粘贴的问题&#xff0c;这里有个pdf解锁文字复制功能的网址&#xff0c;mark一下。超级pdf 参考资料《STM32F429FreeRTOS开发手册_V1.2》 官方资料 FreeRTOS 的源码和相应的官方书籍均可从官…...

【PPT】ppt里面使用svg图标

要想编辑好的PPT&#xff0c;少不了小图标的美化&#xff0c;图标可以使PPT变得更有趣&#xff0c;更易懂&#xff0c;更美观。 对于png&#xff0c;主要处理它的颜色&#xff0c;可使用【重新着色】功能。 对于jpg&#xff0c;主要处理它的背景&#xff0c;删除背景后同png处…...

uni-app:实现页面效果4(echarts数据可视化)

效果 代码 <template><view><view><view class"title">概况</view><view class"line_position"><view class"line1"><view class"item"><view class"one">今日销售…...

vue实现echarts中 9种 折线图图例

let datas [{ DivideScore: 7, UserScore: 7.2, Name: 目标制定 },{ DivideScore: 7, UserScore: 7, Name: 具体性 },{ DivideScore: 7, UserScore: 7.5, Name: 可衡量性 },{ DivideScore: 7, UserScore: 7, Name: 可实现性 },{ DivideScore: 7, UserScore: 7, Name: 时间限定…...

redis实战-实现用户签到UV统计

BitMap功能演示 我们针对签到功能完全可以通过mysql来完成&#xff0c;比如说以下这张表 用户一次签到&#xff0c;就是一条记录&#xff0c;假如有1000万用户&#xff0c;平均每人每年签到次数为10次&#xff0c;则这张表一年的数据量为 1亿条 每签到一次需要使用&#xff08…...

作为创始人的价值观与心法,构建系统

价值观 绿色、健康、有趣、感恩、谦卑、责任、勇气、客观、冷静、自洽、尊重、价值、服务、善良、利他 作为co-founder衡量的一个很重要的标准就是这个人的人品&#xff0c;大家一起做事情的体验要好&#xff0c;才能有large energy&#xff0c;且流通。 乐观、通达&#xf…...

Go语言基础面经

1.go语言编程的好处是什么 编译和运行都很快。 在语言层级支持并行操作。 有垃圾处理器。 内置字符串和 maps。 函数是 go 语言的最基本编程单位。 2.说说go语言的select机制 select 机制用来处理异步 IO 问题 select 机制最大的一条限制就是每个 case 语句里必须是一个…...

服务器文件备份

服务器上&#xff0c;做好跟应用程序有关的文件备份&#xff08;一般备份到远程的盘符&#xff09;&#xff0c;有助于当服务器发生硬件等故障时&#xff0c;可以对系统进行进行快速恢复。 下面以Windows服务器为例&#xff0c;记录如何做文件的备份操作。 具体操作如下&#…...

剑指offer——JZ68 二叉搜索树的最近公共祖先 解题思路与具体代码【C++】

一、题目描述与要求 二叉搜索树的最近公共祖先_牛客题霸_牛客网 (nowcoder.com) 题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。 1.对于该题的最近的公共祖先定义:对于有根树T的两个节点p、q&#xff0c;最近公共祖先LCA(T,p,q)表示一个节点x&#…...

[Spring] @Bean 修饰方法时如何注入参数

目录 一、Bean 的简单使用 1、正常情况 2、问题提出 二、解决方案 1、Qualifier 2、直接写方法名 三、特殊情况 1、DataSource 一、Bean 的简单使用 在开发中&#xff0c;基于 XML 文件配置 Bean 对象的做法非常繁琐且不好维护&#xff0c;因此绝大部分情况下都是使用…...

docker拉取镜像错误 missing signature key

您正在尝试使用 yum 在 CentOS 或 RHEL 系统上安装 docker-ce&#xff0c;但您遇到了一些问题。根据您提供的输出&#xff0c;这里有几个需要注意的点&#xff1a; 系统未注册: "This system is not registered with an entitlement server" 指示您的系统未注册。对于…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

【Java_EE】Spring MVC

目录 Spring Web MVC ​编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 ​编辑参数重命名 RequestParam ​编辑​编辑传递集合 RequestParam 传递JSON数据 ​编辑RequestBody ​…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

《Offer来了:Java面试核心知识点精讲》大纲

文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...