《网络编程实战》学习笔记 Day10

news2024/11/25 23:36:57

系列文章目录

这是本周期内系列打卡文章的所有文章的目录

  • 《Go 并发数据结构和算法实践》学习笔记 Day 1
  • 《Go 并发数据结构和算法实践》学习笔记 Day 2
  • 《说透芯片》学习笔记 Day 3
  • 《深入浅出计算机组成原理》学习笔记 Day 4
  • 《编程高手必学的内存知识》学习笔记 Day 5
  • NUMA内存知识 学习笔记 Day6
  • 《C++并发编程》 学习笔记 Day7
  • 《职场求生攻略》学习笔记 Day8
  • 《网络编程实战》学习笔记 Day9

文章目录

  • 系列文章目录
  • 前言
  • 一、poll是什么?(What)
  • 二、(Why)
    • 对比select认识
  • 三、如何使用,demo实验show me the code?(How)
  • 总结


前言

提示:这里可以添加本文要记录的大概内容:

学习内容:https://time.geekbang.org/column/article/140520
与知识建立主客体之间的联系:
其实内核poll的实现与select的实现类似,但在select之上做了改进,传递的数据结构不同,突破了文件描述符上限的限制。


提示:以下是本篇文章正文内容,下面案例可供参考

一、poll是什么?(What)

背景: select 有一个缺点,那就是所支持的文件描述符的个数是有限的,在 Linux 系统中,select 的默认最大值为 1024。

这就出现了 poll 函数。该 I/O 多路复用技术,突破了文件描述符个数限制。关键是传递给内核的数据结构不同。

poll 函数的原型:

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

第一个参数是一个 pollfd 的数组。注意这里的 events 可以表示多个不同的事件,具体的实现可以通过使用二进制掩码位操作来完成。
关键数据结构pollfd

struct pollfd {
               int   fd;         /* file descriptor */
               short events;     /* requested events */
               short revents;    /* returned events */
           };

events 类型的事件可以分为两大类:

  • 第一类是可读事件
  • 第二类是可写事件

如何查看poll函数代码的实现?TODO

二、(Why)

对比select认识

  1. 性能相近
    有张I/O多路复用的图可以看出select和poll的性能

在这里插入图片描述

  1. 使用限制

和 select 函数对比一下,我们发现 poll 函数和 select 不一样的地方就是,在 select 里面,文件描述符的个数已经随着 fd_set 的实现而固定,没有办法对此进行配置;而在 poll 函数里,我们可以控制 pollfd 结构的数组大小,这意味着我们可以突破原来 select 函数最大描述符的限制。

  1. 其他对比摘录

和 select 非常不同的地方在于,poll 每次检测之后的结果不会修改原来的传入值,而是将结果保留在 revents 字段中,这样就不需要每次检测完都得重置待检测的描述字和感兴趣的事件。我们可以把 revents 理解成“returned events”。
poll 函数有一点非常好,如果我们不想对某个 pollfd 结构进行事件检测,可以把它对应的 pollfd 结构的 fd 成员设置成一个负值。

三、如何使用,demo实验show me the code?(How)

demo:
详见:https://gitee.com/jahentao/experiments/pulls/2/files

TODO 实验还要进行改进

./bin/pollserver

#define INIT_SIZE 128

int main(int argc, char **argv) {
    int listen_fd, connected_fd;
    int ready_number;
    ssize_t n;
    char buf[MAXLINE];
    struct sockaddr_in client_addr;

    listen_fd = tcp_server_listen(SERV_PORT);

    //初始化pollfd数组,这个数组的第一个元素是listen_fd,其余的用来记录将要连接的connect_fd
    struct pollfd event_set[INIT_SIZE];
    event_set[0].fd = listen_fd;
    event_set[0].events = POLLRDNORM;

    // 用-1表示这个数组位置还没有被占用
    int i;
    for (i = 1; i < INIT_SIZE; i++) {
        event_set[i].fd = -1;
    }

    for (;;) {
        if ((ready_number = poll(event_set, INIT_SIZE, -1)) < 0) {
            error(1, errno, "poll failed ");
        }

        if (event_set[0].revents & POLLRDNORM) {
            socklen_t client_len = sizeof(client_addr);
            connected_fd = accept(listen_fd, (struct sockaddr *) &client_addr, &client_len);

            //找到一个可以记录该连接套接字的位置
            for (i = 1; i < INIT_SIZE; i++) {
                if (event_set[i].fd < 0) {
                    event_set[i].fd = connected_fd;
                    event_set[i].events = POLLRDNORM;
                    break;
                }
            }

            if (i == INIT_SIZE) {
                error(1, errno, "can not hold so many clients");
            }

            if (--ready_number <= 0)
                continue;
        }

        for (i = 1; i < INIT_SIZE; i++) {
            int socket_fd;
            if ((socket_fd = event_set[i].fd) < 0)
                continue;
            if (event_set[i].revents & (POLLRDNORM | POLLERR)) {
                if ((n = read(socket_fd, buf, MAXLINE)) > 0) {
                    if (write(socket_fd, buf, n) < 0) {
                        error(1, errno, "write error");
                    }
                } else if (n == 0 || errno == ECONNRESET) {
                    close(socket_fd);
                    event_set[i].fd = -1;
                } else {
                    error(1, errno, "read error");
                }

                if (--ready_number <= 0)
                    break;
            }
        }
    }
}

客户端 1:


$telnet 127.0.0.1 43211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
a
a
aaaaaaaaaaa
aaaaaaaaaaa
afafasfa
afafasfa
fbaa
fbaa
^]


telnet> quit
Connection closed.

客户端 2:


telnet 127.0.0.1 43211
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
b
b
bbbbbbb
bbbbbbb
bbbbbbb
bbbbbbb
^]


telnet> quit
Connection closed.

总结

提示:这里对文章进行总结:

今天的学习,我了解了poll。
poll 是另一种在各种 UNIX 系统上被广泛支持的 I/O 多路复用技术,虽然名声没有 select 那么响,能力一点不比 select 差,而且因为可以突破 select 文件描述符的个数限制,在高并发的场景下尤其占优势。

内容来源:
极客时间:21 | poll:另一种I/O多路复用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/181236.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自制DAPLink 基于ARM官方源码以及STM32F103C8T6

【本文发布于https://blog.csdn.net/Stack_/article/details/128771308&#xff0c;未经许可禁止转载&#xff0c;转载须注明出处】 一、安装工具并配置环境变量 1、python3 【官网】 【网盘】 链接&#xff1a;https://pan.baidu.com/s/1zW_H_eQlkzX3FkXuClFnTA 提取码&#…

python 操作 json 文件的种种知识点

本篇博客将带你全方位了解 Python 操作 json 文件的技术点 让你碰到 json 格式文件不在发愁 文章目录json 模块读取 JSON写入 JSON读取与写入基本用法如下json 模块进阶用法控制输出格式在 JSON 中存储 Python 特殊类型对数据进行验证和清洗第三方模块json 模块 Python 提供了…

CE自动汇编之AOB注入

目录 一、什么是AOB注入&#xff1f; 二、什么时候使用AOB注入&#xff1f; 三、代码注入 四、全部注入 五、“全部注入”和“AOB注入”的分别 六、代码注入与AOB注入的区别 CE自动汇编的模板中&#xff0c;有三种注入代码的方式&#xff1a; 第一种是代码注入&#xff…

Qt使用数据库模型中的删除详解

以下使用 QSqlTableModel 模型&#xff0c;使用tableView显示内容 以下为界面&#xff1a; 这里主要介绍删除操作&#xff1a; 删除一行为&#xff1a; int rowui->tableView->currentIndex().row();//获取行号model->revertRow(row);//删除该行model->submitAll(…

git 关于分支和仓库的理解

何时需要initgit init//初始化本地仓库.git目录如果初始化就会在当前文件夹中出现.git的目录&#xff0c;该目录默认是隐藏的&#xff0c;需要关闭显示隐藏文件才能看到。执行完git init命令后&#xff0c;当前目录就成为了工作区&#xff08;工作区可以理解为操作本地仓库的车…

MyBatis-Plus知识快速入门

文章目录1.MyBatis-Plus简介2.入门案例2.1开发环境2.2创建测试数据库和表2.3创建SpringBoot工程2.4创建实体类以及lombok的使用2.5添加mapper2.6加入日志功能3.基本的CRUD3.1BaseMapper3.2插入3.3删除3.4修改3.5查询4.通用Service4.1创建Service接口和实现类5.常用注解5.1Table…

“华为杯”研究生数学建模竞赛2005年-【华为杯】A题:城市出租车交通规划综合模型(附获奖论文和matlab代码)

赛题描述 A: Highway Traveling time Estimate and Optimal Routing Ⅰ Highway traveling time estimate is crucial to travelers. Hence, detectors are mounted on some of the US highways. For instance, detectors are mounted on every two-way six-lane highways o…

springboot 分布式全局唯一id的生成-雪花算法snowflake

一 背景描述 1.1 问题产生 在分布式系统中&#xff0c;怎么使用全局唯一id&#xff1f; 在分布式是&#xff0c;微服务的架构中&#xff0c;或者大数据分库分表中&#xff0c;多个不同节点怎么保持每台机器生成的主键id不重复&#xff0c;具有唯一性&#xff1f; 方案1&…

【算法基础】归并排序(原理、过程、例题、代码)

一、归并排序原理 1. 算法介绍 归并排序是建立在归并操作上的一种有效,稳定的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有…

力扣 2309. 兼具大小写的最好英文字母

题目 给你一个由英文字母组成的字符串 s &#xff0c;请你找出并返回 s 中的 最好 英文字母。返回的字母必须为大写形式。如果不存在满足条件的字母&#xff0c;则返回一个空字符串。 最好 英文字母的大写和小写形式必须 都 在 s 中出现。 英文字母 b 比另一个英文字母 a 更…

前端食堂技术周刊第 68 期:Astro 2.0、Nuxt v3.1.0、Bun v0.5、TS 实现 Stage 3 Decorators 提案

美味值&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f;&#x1f31f; 口味&#xff1a;萝卜牛腩煲 食堂技术周刊仓库地址&#xff1a;https://github.com/Geekhyt/weekly 本期摘要 Astro 2.0Nuxt v3.1.0Bun v0.5TS 实现 Stage 3 Decorators 提案Turbore…

【算法突击】排序算法系列(一) | 程序员面试 | 冒泡排序 | 快速排序 | 归并排序

【排序算法】 冒泡排序 | 快速排序 | 归并排序 文章目录【排序算法】 冒泡排序 | 快速排序 | 归并排序1. 冒泡排序1.1 核心思想1.2 代码实现2. 快速排序2.1 核心思想2.2 时间复杂度2.2 代码实现3. 归并排序3.1 核心思想3.2 时间复杂度3.3 代码实现1. 冒泡排序 1.1 核心思想 将…

【接口自动化】接口间参数传递的一种解决方案

本文转载自&#xff1a;接口间参数传递的一种解决方案 做过接口自动化测试的同学肯定都熟悉在全链路测试过程中&#xff0c;很多业务场景的完成并非由单一接口实现&#xff0c;而是由很多接口组成的一条链路实现。例如你在淘宝上购物场景。 不同于单接口测试&#xff0c;这种链…

2 线性模型

文章目录一般流程问题引入数据集与测试集过拟合与泛化开发集监督学习和非监督学习问题分析训练集、验证集、测试集模型设计模拟训练过程课程代码课后习题代码课程来源&#xff1a; 链接文档参考&#xff1a; 链接以及 BirandaのBlog&#xff01;一般流程 对于一般的线性模型来…

微信小程序 Springboot校园招聘求职系统

基于微信小程序的校园求职系统的设计基于现有的手机&#xff0c;可以实现首页、个人中心、岗位类型管理、用户管理、企业管理、招聘信息管理、应聘信息管理、系统管理等功能。方便用户对首页、招聘信息、我的等详细的了解及统计分析 一个基本的程序包含app.json、project.confi…

谈谈SpringBoot(二)

1. Spring Boot缓存 1.1 JSR-107 Spring从3.1开始定义了org.springframework.cache.Cache 和org.springframework.cache.CacheManager接口来统一不同的缓存技术&#xff1b; 并支持使用JCache&#xff08;JSR-107&#xff09;注解简化我们开发。 Cache接口为缓存的组件规范定义…

day23|93.复原IP地址、78.子集、90.子集II

93.复原IP地址 有效 IP 地址 正好由四个整数&#xff08;每个整数位于 0 到 255 之间组成&#xff0c;且不能含有前导 0&#xff09;&#xff0c;整数之间用 . 分隔。 例如&#xff1a;"0.1.2.201" 和 "192.168.1.1" 是 有效 IP 地址&#xff0c;但是 &q…

layui框架学习(2:颜色、图标、动画)

B站教学视频中对Layui的颜色没有专门介绍&#xff0c;而Layui官方教程中虽然有颜色章节&#xff0c;但也只是简单介绍了基色调、辅色调、中性的颜色的概念及用途&#xff0c;最后说明layui 内置了七种背景色&#xff0c;以便用于各种元素中&#xff0c;如&#xff1a;徽章、分割…

Go语言基础入门第二章

Go语言环境安装 下载地址&#xff1a;https://golang.google.cn/dl/ 下载完安装包直接安装即可&#xff0c;安装完毕后&#xff0c;打开cmd控制台&#xff0c;输入”go version“查看是否安装成功以及对应安装版本。 配置环境变量Go语言需要一个安装目录&#xff0c;还需要一个…

Spring Cloud_Eureka服务注册与发现

目录一、Eureka基础知识1.什么是服务治理2.什么是服务注册3.Eureka两组件二、单机Eureka构建步骤1.IDEA生成eurekaServer端服务注册中心2.服务提供者3.服务消费者代码链接 https://github.com/lidonglin-bit/cloud 一、Eureka基础知识 1.什么是服务治理 SpringCloud封装了Ne…