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

三、iperf3代码主要架构分析之main函数主要流程

iperf3是一个非常强大的工具,它是用C语言编写的。同时iperf3也是用C语言实现面向对象编程的典范,他以数据结构+函数指针为基础,非常好的用C语言实现面向对象的编程的三大特征:封装,继承,多态。相信通过阅读iperf3的源代码不仅能帮助我们更好的理解与使用iperf3,也可以帮助我们去更好的理解C++及其它面向对象的语言里的类-对象-实例化-多态-模板等概念的本质。

main函数,代码流程

在src/main.c文件里,我们可以找到main函数,除了用TEST_PROC_AFFINITY宏括起来的部分外(TEST_PROC_AFFINITY编译宏是一个未定义宏,所以这部分代码是未启用的,为了阅读方便,在本文中删除了),我们可以看到整个main函数分成4大步骤:

  • 第一步,对象实例化,创建对象test
  • 第二步,根据用户在终端命令行界面输入参数,初始化对象test
  • 第三步,运行对象test,处理测试过程
    • 如果是客户端:发起连接建立,并发送数据包,开始测试
    • 如果是服务端:监听端口,等待接收处理客户端发过来的数据包,开始测试过程
  • 第四步,测试结束,删除销毁对象test
int
main(int argc, char **argv)
{struct iperf_test *test;#ifdef TEST_PROC_AFFINITY//这部分代码是未实现的功能,删除
#endif//第一步对象实例化,创建对象test,并用iperf_defaults()对test里的变量和指针赋默认值test = iperf_new_test();if (!test)iperf_errexit(NULL, "create new test error - %s", iperf_strerror(i_errno));iperf_defaults(test);	/* sets defaults *///第二步,根据用户在终端命令行界面输入参数,初始化对象testif (iperf_parse_arguments(test, argc, argv) < 0) {iperf_err(test, "parameter error - %s", iperf_strerror(i_errno));fprintf(stderr, "\n");usage_long(stdout);exit(1);}//第三步,运行对象test,处理测试过程if (run(test) < 0)iperf_errexit(test, "error - %s", iperf_strerror(i_errno));//第四步,测试结束,删除销毁对象testiperf_free_test(test);return 0;
}

第一步,测试实例的创建–创建对象test

文章开头介绍过,iperf3是用C语言实现面向对象编程的典范, 所以这里第一步,调用iperf_new_test创建对象,C语言里不支持class, 所以这里用struct里:定义数据+函数指针的方式,来实现类的数据属性+成员函数。然后通过malloc给结构指针附值的方式,实现对象(全部结构指针)test的创建与分配内存(class创建对象的本质是给对象分配内存)。以及给test的settings和bitrate_limit_intervals_traffic_bytes二个struct指针进入分配内存。

struct iperf_test *
iperf_new_test()
{struct iperf_test *test;//通过malloc给test指针分配内存---------对象实例化test = (struct iperf_test *) malloc(sizeof(struct iperf_test));if (!test) {i_errno = IENEWTEST;return NULL;}/* initialize everything to zero */memset(test, 0, sizeof(struct iperf_test));//通过malloc给test->settings指针分配内存test->settings = (struct iperf_settings *) malloc(sizeof(struct iperf_settings));if (!test->settings) {free(test);i_errno = IENEWTEST;return NULL;}memset(test->settings, 0, sizeof(struct iperf_settings));//通过malloc给test->bitrate_limit_intervals_traffic_bytes 指针分配内存test->bitrate_limit_intervals_traffic_bytes = (iperf_size_t *) malloc(sizeof(iperf_size_t) * MAX_INTERVAL);if (!test->bitrate_limit_intervals_traffic_bytes) {free(test->settings);free(test);i_errno = IENEWTEST;return NULL;}memset(test->bitrate_limit_intervals_traffic_bytes, 0, sizeof(sizeof(iperf_size_t) * MAX_INTERVAL));/* By default all output goes to stdout */test->outfile = stdout;return test;
}

第二步,测试实例的初始化–根据输入参数,初始化对象test

这一步,本质上是,调用iperf_defaults对test进行初步的初始化,对test里的数据和函数附默认值(比如tcp, udp, sctp分别调用什么函数去进行数据发送与接收,调用什么函数进行连接的函数指针的初始化),这里我们可以把依赖于配置而附不同的函数的函数指针的过程视为虚接口的初始化。这个函数的调用可以视为构造函数的调用。然后读取用户在终端命令行界面上输入的参数,对test进行变量与方法函数的初始化(配置各种属性,以及根据输入参数的不同,比如是测试UDP还是TCP,是客户端还是服务端等等)。

以-c和-s二个参数为例,如果用户输入的命令行为iperf3 -c 则将test初始化为发送端模式,以便后面第三步调用run时可以找到正确的方法(与客户端、服务端,TCP/UDP相应的回调函数)


int
iperf_defaults(struct iperf_test *testp)
{struct protocol *tcp, *udp;
#if defined(HAVE_SCTP_H)struct protocol *sctp;
#endif /* HAVE_SCTP_H */testp->omit = OMIT;testp->duration = DURATION;testp->diskfile_name = (char*) 0;testp->affinity = -1;testp->server_affinity = -1;TAILQ_INIT(&testp->xbind_addrs);
#if defined(HAVE_CPUSET_SETAFFINITY)CPU_ZERO(&testp->cpumask);
#endif /* HAVE_CPUSET_SETAFFINITY */testp->title = NULL;testp->extra_data = NULL;testp->congestion = NULL;testp->congestion_used = NULL;testp->remote_congestion_used = NULL;testp->server_port = PORT;//以代码省略
}int
iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
{static struct option longopts[] ={
/*
此处省略大量代码
*/{"server", no_argument, NULL, 's'},{"client", required_argument, NULL, 'c'},
/*
此处省略大量代码
*/{"version4", no_argument, NULL, '4'},{"version6", no_argument, NULL, '6'},
/*
此处省略大量代码
*/{NULL, 0, NULL, 0}};while ((flag = getopt_long(argc, argv, "p:f:i:D1VJvsc:ub:t:n:k:l:P:Rw:B:M:N46S:L:ZO:F:A:T:C:dI:hX:", longopts, NULL)) != -1) {switch (flag) {
/*
此处省略大量代码
*/        case 's':if (test->role == 'c') {i_errno = IESERVCLIENT;return -1;}iperf_set_test_role(test, 's');break;case 'c':if (test->role == 's') {i_errno = IESERVCLIENT;return -1;}iperf_set_test_role(test, 'c');}break;case '4':test->settings->domain = AF_INET;break;case '6':test->settings->domain = AF_INET6;break;
/*
此处省略大量代码
*/}
/*
此处省略大量代码
*/if ((test->role != 'c') && (test->role != 's')) {i_errno = IENOROLE;return -1;}
/*
此处省略大量代码
*/return 0;
}

第三步,测试实例的执行–运行对象test,处理测试过程

在这里,程序会根据自己是运行在服务端还是客户端模式,执行不同的测试流程:

  • 在服务端:
    程序会打开socket,监听并等待连接;连接成功后,就不停的把客户端送过来的数据读取出来并丢弃,直到连接断开;继续监听并等待新的连接。
  • 在客户端:
  • 程序会打开socket,去连接服务端,连接成功后,按指定测试方式发送数据包,直到测试结束。
static int
run(struct iperf_test *test)
{/*代码删除,内容略*/free(test);
}

相关文章:

三、iperf3代码主要架构分析之main函数主要流程

iperf3是一个非常强大的工具&#xff0c;它是用C语言编写的。同时iperf3也是用C语言实现面向对象编程的典范&#xff0c;他以数据结构函数指针为基础&#xff0c;非常好的用C语言实现面向对象的编程的三大特征&#xff1a;封装&#xff0c;继承&#xff0c;多态。相信通过阅读i…...

【概念辨析】大小端存储

一、情境 在进行内存调试窗口的查看时&#xff0c;是不是会有一种错觉&#xff0c;就是它存的数据与我们预期的都是颠倒的&#xff0c;比如&#xff1a; 这里的a就和我们预期的不是很相同。 二、大小端 大小端是计算机厂家根据自己的习惯制定的关于数据字节序的规则。 1.大端…...

并发编程-学习总结(下)

目录 1、Future 1.1、Callable和Runnable的不同 1.2、Future的主要功能 1.3、常用方法 1.4、Future使用注意事项 1.5、CompletableFuture(旅游平台问题) 1.5.1、需求 1.5.2、解决方案1&#xff1a;串行 1.5.3、解决方案2&#xff1a;线程池 1.5.4、解决方案3&#xf…...

arm汇编指令详细整理及实例详解

目录一、简介二、ARM 汇编指令说明2.1 32位数据操作指令2.2 32位存储器数据传送指令2.3 32位转移指令2.4 其它32位指令三、实例讲解3.1 MRS3.2 MSR3.3 PRIMASK3.4 FAULTMASK3.5 BX指令3.6 零寄存器 wzr、xzr3.7 立即寻址指令3.8 寄存器间接寻址指令3.9 寄存器移位寻址指令3.10 …...

高等数学笔记(下下)

无穷级数 定义 一般的&#xff0c;如果给定一个数列u1,u2,u3,...un,...,u_1, u_2, u_3, ... u_n, ... ,u1​,u2​,u3​,...un​,...,&#xff0c;那么由这个梳理构成的表达式u1u2u3...un...u_1u_2u_3...u_n...u1​u2​u3​...un​...叫做(常数项)无穷级数&#xff0c;简称(常…...

零基础如何入门网络安全(黑客)

我经常会看到这一类的问题&#xff1a; 学习XXX知识没效果&#xff1b;学习XXX技能没方向&#xff1b;学习XXX没办法入门&#xff1b; 给大家一个忠告&#xff0c;如果你完全没有基础的话&#xff0c;前期最好不要盲目去找资料学习&#xff0c;因为大部分人把资料收集好之后&a…...

【C++】map和set用法详解

文章目录1.关联式容器2.键值对3.树形结构的关联式容器3.1 set3.1.1 set的介绍3.1.2 set的模板参数列表3.1.3 set的使用3.2 mapmap的介绍map的模板参数列表map的使用关于map的元素访问总结3.3multimap1.关联式容器 我们接触过STL中的部分容器&#xff0c;比如&#xff1a;vecto…...

BLIP2-图像文本预训练

文章目录摘要解决问题算法模型结构通过frozen图像编码器学习视觉语言表征图像文本对比学习&#xff08;ITC&#xff09;基于图像文本生成&#xff08;ITG&#xff09;图文匹配&#xff08;ITM&#xff09;从大规模语言模型学习视觉到语言生成模型预训练预训练数据预训练图像编码…...

Faster-Rcnn修改转数据集文件

目录 学习python的一些基础知识 argparser assert关键字 让你秒懂Python 类特殊方法__getitem__ lxml.etree.fromstring的使用 统计一下json文件内的种类 正脸红外光 正脸-混合红外光 正脸-交叉偏振光 正脸-平行偏振光 正脸-紫外光 正脸-棕色光 调用mydataset可视化…...

带你沉浸式体验删库跑路

前言:学习的过程比较枯燥,后面会记录一些比较有意思的东西&#xff0c;比如程序员之间流传的删库跑路的梗,当然本次测试是在虚拟机上进行的并进行了快照保护,所以其实没太大问题。首先得要有一个虚拟机要有一个linux iso文件装在虚拟机上以上两点不是本文重点,如果有需要可以私…...

Linux学习(8.5)文件内容查阅

目录 文件内容查阅&#xff1a; 直接检视文件内容 cat (concatenate) tac (反向列示) nl (添加行号列印) 可翻页检视 more (一页一页翻动) less (一页一页翻动) 数据撷取 tail (取出后面几行) 非纯文字档&#xff1a; od 修改文件时间或建置新档&#xff1a; touc…...

【Docker】命令总结

目录 1.镜像命令 1.1拉取镜像 1.2查看镜像 1.3保存镜像 1.4导入镜像 2.容器命令 2.1创建并运行容器 2.2删除容器 2.3进入容器 2.4查看容器状态 2.5暂停容器 2.6恢复容器 2.7停止容器 2.8启动容器 2.8查看容器日志 3.数据卷命令 3.1创建数据卷 3.2查看所有数据…...

并发编程-学习总结(上)

目录 1、线程基础 1.1、线程实现方法 1.2、如何正确停止线程 1.3、Java线程的六种状态 1.4、wait/notify/notifyAll注意事项 1.4.1、为什么 wait 、notify、notifyAll必须在 synchronized 保护的同步代码中使用&#xff1f; 1.4.2、为什么 wait/notify/notifyAll 被定义…...

QT之OpenGL混合

QT之OpenGL混合1. 概述2. 实现2.1 丢弃片段2.1.1 Demo2.2 混合2.2.1 相关函数2.2.2 排序问题2.2.3 Demo1. 概述 OpenGL中&#xff0c;混合(Blending)通常是实现物体透明度(Transparency)的一种技术。 2. 实现 2.1 丢弃片段 在某些情况下&#xff0c;有些片段是只需要设置显…...

【1255. 得分最高的单词集合】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 你将会得到一份单词表 words&#xff0c;一个字母表 letters &#xff08;可能会有重复字母&#xff09;&#xff0c;以及每个字母对应的得分情况表 score。 请你帮忙计算玩家在单词拼写游戏中所能获…...

nginx模块介绍

新编译前&#xff0c;在对应的nginx原编译文件夹 如&#xff1a;nginx-1.23.0 下&#xff0c;要 make clean 清空以前编译的objs文件夹&#xff0c;实际上就是执行了rm objs文件夹。 很多要用到git&#xff0c;先yum install git -y echo-nginx-module 让nginx直接使用echo的…...

排错工具ping和trace(电子科技大学TCP/IP实验四)

一&#xff0e;实验目的 1、了解网络连通性测试的方法和工作原理 2、了解网络路径跟踪的方法和工作原理 3、掌握 MTU 的概念和 IP 分片操作 4、掌握 IP 分组生存时间&#xff08;TTL&#xff09;的含义和作用 5、掌握路由表的作用和路由查找算法 二&#xff0e;预备知识 …...

node.js中ws模块创建服务端和客户端

一、WebSocket出现的原因 1、Http协议发布REST API 的不足&#xff1a; 每次请求响应完成之后&#xff0c;服务器与客户端之间的连接就断开了&#xff0c;如果客户端想要继续获取服务器的消息&#xff0c;必须再次向服务器发起请 求。这显然无法适应对实时通信有高要求的场景…...

kubernates-1.26.1 kubeadm containerd 单机部署

k8s1.26 kubeadm containerd 安装 kubeadm init 时提示 containerd 错误 failed to pull image “k8s.gcr.io/pause:3.6” 报错日志显示containerd pull时找不到对应的pause版本&#xff0c;而不是registry.k8s.io/pause:3.9 [rootk8s-master containerd]# kubeadm init --k…...

如何在 iPhone 上恢复已删除的通话记录/通话记录

您的通话记录/通话记录可能很重要&#xff0c;尤其是当您想要拨打之前联系过但未保存的号码时。如果您碰巧删除了通话记录&#xff08;有意或无意&#xff09;&#xff0c;本指南将帮助您了解如何检索它们并找回您需要使用的所有记录。我们将根据您的情况和您拥有的工具讨论不同…...

网络六边形受到攻击

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 抽象 现代智能交通系统 &#xff08;ITS&#xff09; 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 &#xff08;…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

3.3.1_1 检错编码(奇偶校验码)

从这节课开始&#xff0c;我们会探讨数据链路层的差错控制功能&#xff0c;差错控制功能的主要目标是要发现并且解决一个帧内部的位错误&#xff0c;我们需要使用特殊的编码技术去发现帧内部的位错误&#xff0c;当我们发现位错误之后&#xff0c;通常来说有两种解决方案。第一…...

Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件

今天呢&#xff0c;博主的学习进度也是步入了Java Mybatis 框架&#xff0c;目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学&#xff0c;希望能对大家有所帮助&#xff0c;也特别欢迎大家指点不足之处&#xff0c;小生很乐意接受正确的建议&…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“&#x1f916;手搓TuyaAI语音指令 &#x1f60d;秒变表情包大师&#xff0c;让萌系Otto机器人&#x1f525;玩出智能新花样&#xff01;开整&#xff01;” &#x1f916; Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制&#xff08;TuyaAI…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

抽象类和接口(全)

一、抽象类 1.概念&#xff1a;如果⼀个类中没有包含⾜够的信息来描绘⼀个具体的对象&#xff0c;这样的类就是抽象类。 像是没有实际⼯作的⽅法,我们可以把它设计成⼀个抽象⽅法&#xff0c;包含抽象⽅法的类我们称为抽象类。 2.语法 在Java中&#xff0c;⼀个类如果被 abs…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...