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

C++Linux网络编程:poll模型和简单使用

文章目录

    • poll模型
      • pollfd结构体
      • nfds_t的定义
    • 一个简单的poll服务器
    • 总结

poll模型

poll模型和select模型类似,都是在指定时间内轮询一定数量的文件描述符,以测试其中是否有就绪者,需要使用头文件poll.h

#include <poll.h>
int poll(struct pollfd* fds, nfds_t nfds, int timeout);

在select中使用的是fd_set结构体,而在此处的是pollfd和nfds_t,timeout的作用和select的一样,用于指定poll的超时值:当timeout的值为-1时,poll调用将会永远阻塞,直到某个事件发生;当timeout为0时,poll调用将立即返回
poll的返回值也和select一致,表示就绪文件描述符的总数。

pollfd结构体

struct pollfd{int fd; // 文件描述符short int events; // 注册的事件short int revents; // 实际发生的事件,由内核填充
};
  • fd指定文件描述符
  • events成员告诉poll监听fd上的哪些事件,它是一系列事件的按位或
  • revents成员由内核修改,以通知应用程序fd上实际发生了哪些事件

poll支持以下事件类型:

事件描述是否可作为输入是否可作为输出
POLLIN数据(包括普通数据和优先数据)可读
POLLRNDORM普通数据可读
POLLRDBAND优先级带数据可读
POLLPRI高优先级数据可读,比如TCP带外数据
POLLOUT数据(包括普通数据和优先数据)可写
POLLWRNORM普通数据可写
POLLWRBAND优先级带数据可写
POLLRDHUPTCP连接被对方关闭,或者对方关闭了写操作。它由GNU引入
POLLERR错误
POLLHUP挂起。比如管道的写端被关闭后,读端描述符上将收到POLLHUP事件
POLLNVAL文件描述符没有打开

在表中提到了很多事件,但是Linux中没有完全支持它们
通常,应用程序需要根据recv调用的返回值来区分socket上接受到的是有效数据还是对方关闭连接的请求,并做相应的处理。

不过,自Linux内核2.6.17开始,GNU为poll系统调用增加了一个POLLRDHUP事件,它在socket上接收到对方关闭连接的请求后触发。这为我们区分recv接受到的数据是有效数据还是对方关闭连接的请求提供了一种更简单的方式。
但使用POLLRDHUP事件时,我们需要在代码最开始处定义_GNU_SOURCE

nfds_t的定义

typedef unsigned long int nfds_t;

该参数用来指定被监听事件集合fds的大小

一个简单的poll服务器

这个服务器是个简单的echo服务器:

#include <iostream>
#include <vector>
#include <sys/socket.h>
#include <poll.h>
#include <algorithm>
#include <arpa/inet.h>
#include <assert.h>
#include <vector>
#include <unistd.h>using namespace std;int main(int argc, char* argv[]){if(argc != 3){cerr << "格式为 ip port" << endl;return 1;}int serverSocket, clientSocket;/*这个头文件在in.h中(实际上我们调用的是inet/in.h而inet/in.h被包含在头文件arpa/inet。h中了*/struct sockaddr_in serverAddr{}, clientAddr{};socklen_t clientAddrLen;// 创建监听套接字serverSocket = socket(AF_INET, SOCK_STREAM, 0);assert(serverSocket != -1);serverAddr.sin_family = AF_INET;/*htons的英文意思是host to network shrot用于将16位无符号短整型(port)的主机字节序转换为网络字节序*/serverAddr.sin_port = htons(stoi(argv[2])); /*在调用 inet_pton 函数时,需要将 &(address.sin_addr) 作为参数传递,而不是 &(address.sin_addr.s_addr)struct sockaddr_in 结构体中的 sin_addr 字段是一个 struct in_addr 类型的结构体它包含了 IP 地址的二进制表示形式。in_addr 结构体中的 s_addr 字段实际上就是一个无符号整数类型(uint32_t)用来存储 IP 地址的二进制形式。*/inet_pton(AF_INET, argv[1], &(serverAddr.sin_addr));// 绑定套接字到地址和端口int ret = bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr));assert(ret != -1);ret = listen(serverSocket, 5);assert(ret != -1);// 监听的文件描述符队列/*创建一个pollfd类型的空向量并且将之前创建的serverSocket加入到其中进行监听POLLIN是我们所监视的事件类型,这点笔记中有写为什么需要监视serverSocket?答:这是为了实现服务器的异步IO,通过监视serverSocket及时检测到下面两种情况:1. 当有新的客户端连接请求到达时,我们希望能够立即进行处理。通过监视serverSocket上的POLLIN事件,可以检测到是否有客户端尝试建立连接2. 当serverSocket上出现其他错误情况(如连接断开或发生错误)时,我们也希望能及时进行处理通过监视serverSocket上的激长时间,如POLLHUP或POLLERR,可以检测到这些错误情况*/vector<pollfd> fds;fds.push_back({serverSocket, POLLIN});while(true){int numRead = poll(fds.data(), fds.size(), -1);if(numRead < 0){cerr << "poll error";return 1;}// for(auto &fd : fds){/*确保有新的连接但是不是很理解为什么是一直监听serverSocket*/if(fd.fd == serverSocket && fd.revents & POLLIN){// 有新连接clientAddrLen = sizeof(clientAddr);clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrLen);if(clientSocket < 0){cerr << "Failed to accepted connection" << endl;return 1;}else{cout << "New connection from:" << inet_ntoa(clientAddr.sin_addr) << endl;fds.push_back({clientSocket, POLLIN});}}else if(fd.revents & POLLIN){// 需要读取信息// 此时的不是监听socket,而是客户端的连接socketchar buffer[1024];ssize_t bytesRead = recv(fd.fd, buffer, sizeof(buffer), 0);if(bytesRead <= 0){if(bytesRead < 0){cerr << "Error reading from client." << endl;}else{cout << "Connection clost by client." << endl;}close(fd.fd);// 这个remove_if()不是很熟fds.erase(remove_if(fds.begin(), fds.end(),[&](const pollfd& pfd){ return pfd.fd == fd.fd; }),fds.end());}else{// 处理数据cout << "Received data: " << string(buffer, bytesRead) << endl;// 将收到的数据回发给客户端send(fd.fd, buffer, bytesRead, 0);}}}}// 关闭监听套接字close(serverSocket);return 0;
}

总结

学到这里我就发现:想要真正去理解Linux网络编程,还是要懂Linux内核,比如:套接字和文件描述符的联系?要去了解下select和poll的工作原理,这样才能理解程序为何这么编写。

相关文章:

C++Linux网络编程:poll模型和简单使用

文章目录 poll模型pollfd结构体nfds_t的定义 一个简单的poll服务器总结 poll模型 poll模型和select模型类似&#xff0c;都是在指定时间内轮询一定数量的文件描述符&#xff0c;以测试其中是否有就绪者&#xff0c;需要使用头文件poll.h&#xff1a; #include <poll.h>…...

Excel模板2:进度条甘特图

Excel模板2&#xff1a;进度条甘特图 ‍ 今天复刻B站up【名字叫麦兜的狗狗】的甘特图&#xff1a;还在买Excel模板吗&#xff1f;自己做漂亮简洁的甘特图吧&#xff01;_哔哩哔哩_bilibili 阿里网盘永久分享&#xff1a;https://www.alipan.com/s/cXhq1PNJfdm 当前效果&…...

数据结构:4_二叉树

二叉树 一.树概念及结构 1. 树的概念 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树&#xff0c;也就是说它是根朝上&#xff0c;而叶朝下的。 有一个**特殊的…...

设计模式之:状态模式(State Pattern)

状态模式&#xff08;State Pattern&#xff09; 状态模式是一种行为设计模式&#xff0c;允许一个对象在其内部状态改变时改变它的行为。这种模式通过把状态的变化逻辑分布到State的子类之间&#xff0c;减少了相互间的依赖&#xff0c;使得状态的切换更加清晰。 状态模式的…...

【微服安全】API密钥和令牌与微服务安全的关系

什么是 API 密钥和令牌 API 密钥 API 密钥是一串用于识别应用程序或用户的字符串。它通常用于授权应用程序或用户访问 API。API 密钥可以是公开的&#xff0c;也可以是私有的。公开的 API 密钥可供任何人使用&#xff0c;而私有的 API 密钥只能由授权的应用程序或用户使用。 …...

Mock.js

在开发后端的应用中&#xff0c;我们使用postman来测试接口&#xff0c;观察和验证前后端之间的数据传递是否正常。 在开发前端的应用中&#xff0c;我们使用Mock.js来模拟后端服务&#xff0c;以便进行前端业务逻辑的开发和测试。 一般情况下&#xff0c;个人开发或者小团队开…...

【c++】list详细讲解

> 作者简介&#xff1a;დ旧言~&#xff0c;目前大二&#xff0c;现在学习Java&#xff0c;c&#xff0c;c&#xff0c;Python等 > 座右铭&#xff1a;松树千年终是朽&#xff0c;槿花一日自为荣。 > 目标&#xff1a;熟悉list库 > 毒鸡汤&#xff1a;你的脸上云淡…...

C#面:在.NET中 类 System.Web.UI.Page 可以被继承吗?

可以。 它是 ASP.NET WebForms中的一个重要类&#xff0c;用于表示 Web 页面。通过继承 System.Web.UI.Page 类&#xff0c;可以创建自定义的 Web 页面&#xff0c;并在其中添加自己的逻辑和功能。 继承 System.Web.UI.Page 类的好处是&#xff0c;可以重用和扩展已有的功能。…...

AI:128-基于机器学习的建筑物能源消耗预测

🚀点击这里跳转到本专栏,可查阅专栏顶置最新的指南宝典~ 🎉🎊🎉 你的技术旅程将在这里启航! 从基础到实践,深入学习。无论你是初学者还是经验丰富的老手,对于本专栏案例和项目实践都有参考学习意义。 ✨✨✨ 每一个案例都附带有在本地跑过的关键代码,详细讲解供…...

php基础学习之可变函数(web渗透测试关键字绕过rce和回调函数)

可变函数 看可变函数的知识点之前&#xff0c;蒟蒻博主建议你先去看看php的可变变量&#xff0c;会更加方便理解&#xff0c;在本篇博客中的第五块知识点->php基础学习之变量-CSDN博客 描述 当一个变量所保存的值刚好是一个函数的名字&#xff08;由函数命名规则可知该值必…...

MongoDB聚合操作符:$acos

$acos操作符返回一个值的反余弦。从MongoDB4.2版本开始支持。 语法 { $acos: <expression> }$acos接受任何可被解析为值在-1到1之间的表达式&#xff0c;即&#xff1a;-1 < value < 1$acos返回值以弧度为单位&#xff0c;使用$radiansToDegrees操作符可以把输出…...

开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)

文章目录 前言源码获取一、认识PDFBox二、导入依赖三、基础功能demo1&#xff1a;读取pdf所有内容demo2&#xff1a;读取所有页内容&#xff08;分页&#xff09;demo3&#xff1a;添加页眉、页脚demo4&#xff1a;添加居中45文字水印demo5&#xff1a;添加图片到右上角 参考文…...

微软.NET6开发的C#特性——委托和事件

我是荔园微风&#xff0c;作为一名在IT界整整25年的老兵&#xff0c;看到不少初学者在学习编程语言的过程中如此的痛苦&#xff0c;我决定做点什么&#xff0c;下面我就重点讲讲微软.NET6开发人员需要知道的C#特性&#xff0c;然后比较其他各种语言进行认识。 C#经历了多年发展…...

卷积神经网络的基本结构

卷积神经网络的基本结构 与传统的全连接神经网络一样&#xff0c;卷积神经网络依然是一个层级网络&#xff0c;只不过层的功能和形式发生了变化。 典型的CNN结构包括&#xff1a; 数据输入层&#xff08;Input Layer&#xff09;卷积层&#xff08;Convolutional Layer&#x…...

python:使用GDAL库读取遥感影像指定行列数/经纬度坐标的像素值

作者:CSDN @ _养乐多_ 本文将介绍如何使用GDAL库来读取单波段遥感影像数据,如何获取指定行列位置的像素的经纬度坐标,并根据像素行列数或者经纬度坐标获取像素值。代码由python实现。 文章目录 一、读取影像二、获取指定行列位置的像素坐标三、根据地理坐标获取像素值四、根…...

Redis篇----第一篇

系列文章目录 文章目录 系列文章目录前言一、什么是 Redis?二、Redis 与其他 key-value 存储有什么不同?三、Redis 的数据类型?四、使用 Redis 有哪些好处?五、Redis 相比 Memcached 有哪些优势?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住…...

C语言-----用二维数组解决菱形的打印问题

1.打印菱形&#xff0c;多组输入&#xff0c;一个整数&#xff08;2~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成“X”的反斜线和正斜线的长度。 #include <stdio.h>int main() {int n0;while(scanf("%d",&n)! EOF){int i0;int j0;f…...

.NET Core WebAPI中使用swagger版本控制,添加注释

一、效果 二、实现步骤 在代码中添加注释 在项目属性中生成API文档 在Program中注册Swagger服务并配置文档信息 // 添加swagger注释 builder.Services.AddSwaggerGen(x > {x.SwaggerDoc("v1", new OpenApiInfo { Title "Swagger标题", Version "…...

css篇---移动端适配的方案有哪几种

移动端适配 移动端适配是指同一个页面可以在不同的移动端设备上都有合理的布局。主流实现的方案有 响应式布局通过rem或者vw,vh 等实现不同设备有相同的比例而实现适配 首先需要了解viewport 【视口】 视口代表了一个可看见的多边形区域&#xff08;通常来说是矩形&#xff0…...

一、部署Oracle

部署Oracle 一、Docker部署1.Oracle11g1.1 测试环境1.1.1 拉取镜像1.1.2 启动容器1.1.3 配置容器环境变量1.1.4 修改sys、system用户密码1.1.5 创建表空间1.1.6 创建用户并授权1.1.5 使用DBeaver测试连接 二、安装包部署 一、Docker部署 1.Oracle11g 1.1 测试环境 当前只能用…...

使用VSCode开发Django指南

使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架&#xff0c;专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用&#xff0c;其中包含三个使用通用基本模板的页面。在此…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

使用分级同态加密防御梯度泄漏

抽象 联邦学习 &#xff08;FL&#xff09; 支持跨分布式客户端进行协作模型训练&#xff0c;而无需共享原始数据&#xff0c;这使其成为在互联和自动驾驶汽车 &#xff08;CAV&#xff09; 等领域保护隐私的机器学习的一种很有前途的方法。然而&#xff0c;最近的研究表明&…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代&#xff0c;智能代理&#xff08;agents&#xff09;不再是孤立的个体&#xff0c;而是能够像一个数字团队一样协作。然而&#xff0c;当前 AI 生态系统的碎片化阻碍了这一愿景的实现&#xff0c;导致了“AI 巴别塔问题”——不同代理之间…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南

1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发&#xff0c;使用DevEco Studio作为开发工具&#xff0c;采用Java语言实现&#xff0c;包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...