九,iperf3源代码分析:main函数主要流程,正向TCP单向测试时服务端和客户端的交互过程详解

简述

这里把iperf3的正向TCP单向测试时服务端和客户端的交互过程详解,画成了图。
只描述了二侧的测试流程,具体代码调用过程可以参考另外二个文章。
七,iperf3源代码分析:状态机及状态转换过程—>运行正向TCP单向测试时的服务端代码
八,iperf3源代码分析:状态机及状态转换过程—>运行正向TCP单向测试时的客户端代码

客户端和服务端交互过程以及状态机迁移图

在这里插入图片描述

附件

CSDN不支持sequenceDiagram, 所以在https://mermaid-js.github.io/mermaid-live-editor/这个网站编辑后贴图过来,原始文档见底下。

sequenceDiagram
    
    note left of iperf3客户端: 先运行服务端,再运行客户端
    note right of iperf3服务端: 先运行服务端,再运行客户端
    

    iperf3服务端 ->> iperf3服务端 : main进入启动iperf3iperf3服务端
    iperf3服务端 ->> iperf3服务端 : 调用iperf_new_test创建并初始化测试对象
    note over iperf3服务端: 进入:初始化状态
    iperf3服务端 ->> iperf3服务端 : 读取配置参数,并创建服务端监听端口
    note over iperf3服务端: 进入:IPERF_START状态

    iperf3客户端 ->> iperf3客户端 : main进入启动iperf3客户端
    iperf3客户端 ->> iperf3客户端 : 调用iperf_new_test创建并初始化测试对象
    note over iperf3客户端: 进入:初始化状态
    iperf3客户端 ->> iperf3服务端 : 读取配置参数,向服务端发起连接请求,
    iperf3服务端 ->> iperf3服务端 : 调用select/accept函数建立控制链接
    note over iperf3服务端: 进入:PARAM_EXCHANGE状态
    iperf3服务端 ->> iperf3客户端 : 通过控制链接发送PARAM_EXCHANGE指令
    note over iperf3客户端: 进入:PARAM_EXCHANGE状态
    iperf3客户端 ->> iperf3服务端 : 发送用户命令行输入配置参数给服务端
    iperf3服务端 ->> iperf3服务端 : 保存配置参数,并让配置参数生效
    note over iperf3服务端: 进入:CREATE_STREAM状态 
    iperf3服务端 ->> iperf3客户端 : 通过控制链接发送CREATE_STREAM指令
    note over iperf3客户端: 进入:CREATE_STREAM状态
    iperf3客户端 ->> iperf3服务端 : 调用iperf_create_streams函数,创建TCP测试流实例 
    iperf3客户端 ->> iperf3客户端 : 调用iperf_handle_message_client()等待服务端发起新的指令
    iperf3服务端 ->> iperf3服务端 : 调用iperf_tcp_accept接受连接请求
    iperf3服务端 ->> iperf3服务端 : 调用iperf_add_stream创建TCP测试流实例
    note over iperf3服务端: 进入:TEST_START状态 
    iperf3服务端 ->> iperf3客户端 : 通过控制链接发送TEST_START指令
    iperf3服务端 ->> iperf3服务端 :  创建服务端为TCP测试流使用的各种定时器及其它资源
    note over iperf3客户端: 进入:TEST_START状态 
    note over iperf3服务端: 进入:TEST_RUNNING状态 
    iperf3客户端 ->> iperf3客户端 : 开始创建客户端为TCP测试流使用的各种定时器及其它资源
    iperf3客户端 ->> iperf3客户端 : 等待服务端发过来的下一条命令
    iperf3服务端 ->> iperf3客户端 : 通过控制链接发送TEST_RUNNING指令
    note over iperf3客户端: 进入:TEST_RUNNING状态 
    iperf3客户端 ->>  iperf3服务端 : 通过调用iperf_send函数里的sp->snd和test->protocol->send二个函数指针,
    iperf3客户端 ->>  iperf3服务端 : 最终调用iperf_tcp_send()函数向服务端发送测试数据开始测试
    iperf3服务端 ->>  iperf3服务端 : 调用iperf_run_server函数,直接进入TEST_RUNNING分支后,
    iperf3服务端 ->>  iperf3服务端 : 调用iperf_recv函数里的sp->rcv和test->protocol->recv二个函数指针
    iperf3服务端 ->>  iperf3服务端 : 最终调用iperf_tcp_recv()函数接收客户端发过来的测试数据,
    iperf3客户端 ->>  iperf3服务端 : ......
    iperf3客户端 ->>  iperf3服务端 : 最终调用iperf_tcp_send()函数向服务端发送测试数据开始测试
    iperf3客户端 ->>  iperf3服务端 : 直到本次测试完成
    iperf3服务端 ->>  iperf3服务端 : 并做统计,直到所有测试数据接收处理完毕,
    note over iperf3客户端: 进入:TEST_END状态 
    iperf3服务端 ->>  iperf3服务端 : 等待客户端通过控制链接发过来的TEST_END控制信息。
    iperf3客户端 ->>  iperf3服务端 : 通过控制链接发送TEST_END指令
    iperf3客户端 ->>  iperf3客户端 : 等待服务端发送EXCHANGE_RESULT指令
    note over iperf3服务端: 进入:TEST_END状态 
    iperf3服务端 ->>  iperf3服务端 : 通过test->stats_callback(test)和test->reporter_callback(test)二个函数指针,
    iperf3服务端 ->>  iperf3服务端 : 调用iperf_stats_callback和iperf_reporter_callback
    iperf3服务端 ->>  iperf3服务端 : 进行测试结果汇总和生成测试报告
    note over iperf3服务端: 进入:EXCHANGE_RESULT状态 
    iperf3服务端 ->>  iperf3客户端 : 通过控制链接发送EXCHANGE_RESULT指令
    iperf3服务端 ->>  iperf3服务端 : 调用iperf_exchange_result()函数,等待客户端发过来的测试报告
    note over iperf3客户端: 进入:EXCHANGE_RESULT状态 
    iperf3客户端 ->>  iperf3服务端 : 调用iperf_exchange_result()函数,向服务端发送的测试报告
    iperf3客户端 ->>  iperf3客户端 : 等待服务端发送DISPLAY_RESULT指令
    note over iperf3服务端: 进入:DISPLAY_RESULT状态 
    iperf3服务端 ->>  iperf3客户端 : 通过控制链接发送DISPLAY_RESULT指令
     iperf3服务端 ->>  iperf3服务端 : 打印测试报告
    iperf3服务端 ->>  iperf3服务端 : 等待服务端发送IPERF_DONE指令
    note over iperf3客户端: 进入:DISPLAY_RESULT状态 
    iperf3客户端 ->>  iperf3客户端 : 客户端主动发起打印测试报告,
    note over iperf3客户端: 进入:IPERF_DONE状态 
    iperf3客户端 ->>  iperf3服务端 : 并向服务端发IPERF_DONE指令
    iperf3客户端 ->>  iperf3客户端 : 退出iperf3客户端,测试结束
    note over iperf3服务端: 进入:IPERF_DONE状态

    iperf3服务端 ->>  iperf3服务端 : 调用run()–>iperf_run_server()–>iperf_reset_test()函数,reset测试对象test,
    note over iperf3服务端: 进入:初始化状态
    iperf3服务端 ->>  iperf3服务端 : 重新运行初始化,建立监听端口,
    note over iperf3服务端: 进入:IPERF_START状态,
    iperf3服务端 ->>  iperf3服务端 : 等待下一次测试的开始。   
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以参考以下代码来实现C++的压力测试工具,这里以iperf为例,包括客户端服务端代码: 服务端代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <errno.h> #define PORT 5001 #define MAXLINE 1024 int main(int argc, char **argv) { int listenfd, connfd; struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; char buf[MAXLINE]; ssize_t n; if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(EXIT_FAILURE); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(PORT); if (bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) { perror("bind"); exit(EXIT_FAILURE); } if (listen(listenfd, 5) == -1) { perror("listen"); exit(EXIT_FAILURE); } printf("server listening on port %d...\n", PORT); while (1) { cliaddr_len = sizeof(cliaddr); if ((connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &cliaddr_len)) == -1) { perror("accept"); exit(EXIT_FAILURE); } printf("connection from %s, port %d\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)); while ((n = read(connfd, buf, MAXLINE)) > 0) { if (write(connfd, buf, n) != n) { perror("write"); exit(EXIT_FAILURE); } } if (n < 0) { perror("read"); exit(EXIT_FAILURE); } close(connfd); } return 0; } ``` 客户端代码: ``` #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <sys/socket.h> #include <arpa/inet.h> #include <errno.h> #define PORT 5001 #define MAXLINE 1024 int main(int argc, char **argv) { int sockfd; struct sockaddr_in servaddr; char sendline[MAXLINE], recvline[MAXLINE]; ssize_t n; if (argc != 2) { fprintf(stderr, "usage: %s <server IP address>\n", argv[0]); exit(EXIT_FAILURE); } if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(EXIT_FAILURE); } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons(PORT); if (inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) { fprintf(stderr, "inet_pton error for %s\n", argv[1]); exit(EXIT_FAILURE); } if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) == -1) { perror("connect"); exit(EXIT_FAILURE); } printf("connected to server on %s:%d\n", argv[1], PORT); while (fgets(sendline, MAXLINE, stdin) != NULL) { if (write(sockfd, sendline, strlen(sendline)) == -1) { perror("write"); exit(EXIT_FAILURE); } if ((n = read(sockfd, recvline, MAXLINE)) == -1) { perror("read"); exit(EXIT_FAILURE); } recvline[n] = '\0'; if (fputs(recvline, stdout) == EOF) { perror("fputs"); exit(EXIT_FAILURE); } } if (n < 0) { perror("read"); exit(EXIT_FAILURE); } close(sockfd); return 0; } ``` 这段代码实现了一个简单的TCP服务器和客户端,服务器监听本地的5001端口,客户端连接到指定的服务器IP和端口,发送一条消息并等待回复。您可以根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值