OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7904|回复: 2

[XILINX] 【正点原子FPGA连载】第三十二章 基于lwip的TCP服务器性能测试实验--摘自【正点原子】领航者ZYNQ之嵌入式开发指南_V1.2

[复制链接]

1117

主题

1128

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4667
金钱
4667
注册时间
2019-5-8
在线时间
1224 小时
发表于 2020-10-26 11:28:39 | 显示全部楼层 |阅读模式
1)实验平台:正点原子领航者ZYNQ开发板
2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-301505-1-1.html
4)对正点原子FPGA感兴趣的同学可以加群讨论:712557122
5)关注正点原子公众号,获取最新资料更新
1.jpg
1120.png


第三十二章 基于lwipTCP服务器性能测试实验

上一章的lwip Echo Server实验让我们对lwip有一个基本的了解,而Echo Server是基于TCP协议的。TCP协议是为了在不可靠的互联网络上提供可靠的端到端字节流而专门设计的一个传输协议。本章我们将了解lwip tcp协议的使用并测试lwip tcp服务的性能。本章分为以下几个部分:
1.1        简介
1.2        实验任务
1.3        硬件设计
1.4        软件设计
1.5        下载验证


1.1 简介
1)      TCP 协议简介
TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。在开放系统互连OSI参考模型中,它完成第四层传输层所指定的功能,UDP(User Datagram Protocol,用户数据报协议)是同一层内另一个重要的传输协议。在因特网协议族(Internet protocol suite)中,TCP层是位于IP层之上,应用层之下的中间层。不同主机的应用层之间经常需要可靠的、像管道一样的连接,但是IP层不提供这样的流机制,而是提供不可靠的包交换。
应用层向TCP层发送用于网间传输的、用8位字节表示的数据流,然后TCP把数据流分区成适当长度的报文段(通常受该计算机连接的网络的数据链路层的最大传输单元(MTU)的限制)。之后TCP把报文段传给IP层,由它来通过网络将报文段传送给接收端的TCP层。TCP为了保证报文传输的可靠,就给每个包一个序号,同时序号也保证了传送到接收端的数据包能被按序接收。然后接收端对已成功收到的字节发回一个相应的确认(ACK);如果发送端在 合理的往返时延(RTT)内未收到确认,那么对应的数据(假设丢失了)将会被重传。
在数据正确性与合法性上,TCP用一个校验和函数来检验数据是否有错误,在发送和接收时都要计算校验和。在保证可靠性上,采用超时重传和捎带确认机制。在流量控制上,采用滑动窗口协议,协议中规定,对于窗口内未经确认的分组需要重传。在拥塞控制上,采用TCP拥塞控制算法。
作为与TCP协议处于同一层的UDP协议,我们简单的介绍下两者的区别:
1、TCP协议面向连接,是流传输协议,通过连接发送数据,而UDP协议传输不需要连接,是数据报协议;
2.TCP为可靠传输协议,而UDP为不可靠传输协议。即TCP协议可以保证数据的完整和有序,而UDP不能保证;
3.UDP由于不需要连接,故传输速度比TCP快,且占用资源比TCP少;
4.应用场合:TCP协议常用在对数据文件完整性较高的一些场景中,如文件传输等。UDP常用于对通讯速度有较高要求或者传输数据较少时,比如对速度要求较高的视频直播和传输数据较少的QQ等。
2)      TCP首部  
图 34.1.1体现了以太网协议体系分层设计的思想。发送端在应用层将需要传输的数据传给传输层,传输层对应用层的数据进行处理、封装,如果使用TCP协议,则对数据处理后加上TCP标识头进行封装,如果使用UDP协议,则添加UDP标识头进行封装,封装后的数据传递给网络层。网络层对传输层下发的数据处理后添加IP标识头进而传递给数据链路层。数据链路层将网络层下发的数据打包成以太网数据包递交给物理层传输。接收端接收到以太网数据包后进行反向操作从而得到发送端应用层发送的数据。
file:///C:/Users/WCY/AppData/Local/Temp/msohtmlclip1/01/clip_image002.jpg

image002.jpg
图 34.1.2 以太网包数据格式
下图是TCP报文段标识头,在没有选项的情况下,它通常是20个字节。
image004.jpg

图 34.1.3 TCP报文段标识头
源端口号和目的端口号用于寻找发送端和接收端的应用进程,这个和UDP报文相同,这两个值加上IP首部中的源IP地址和目的IP地址唯一确定一个TCP连接。
序列号字段用来标识从TCP发送端向TCP接收端发送的数据字节流,它表示在这个报文段中的第一个数据字节。当建立一个新的连接时,握手报文中的SYN标志置1,这个握手报文中的序号字段为随机选择的初始序号ISN(Initial Sequence Number),当连接建立好以后发送方要发送的第一个字节序号为ISN+1。
确认号字段只有在ACK为1的时候才有用,确认号中包含发送确认的一方所期望收到的下一个序号,确认号是在上一次成功接收到的数据字节序列号上加一,例如上次接收成功接收到对方发过来的数据序号为X,那么返回的确认号就应该为X+1。
头部长度也叫首部长度,首部长度中给出了首部的长度,以32bit也就是4字节为单位,这个字段有4bit,因此TCP最多有60字节的首部,如果没有任何的选项字段,正常的首部长度是20字节。
TCP首部中还有6个标志比特,这6个标志位的说明如下表所示。
表34.1.1 TCP 首部标志位说明
lALPBFf_7-ssA1zMyM0B6w_491_200.png
窗口尺寸也就窗口大小,其中填写相应的值以通知对方自己期望接收的字节数,窗口大小字段是TCP流量控制的关键字段,窗口大小是一个16bit的字段,因此窗口大小最大为65535字节。
16位的校验和覆盖了整个TCP报文段:TCP首部和TCP数据。校验和首先在数据发送方通过特殊的算法计算得出,在传递到接收方之后,还需要再重新计算。如果某个数据报在传输过程中被第三方篡改或者由于线路噪音等原因受到损坏,发送和接收方的校验计算和将不会相符,由此UDP协议可以检测是否出错。
紧急指针只有在URG置1时有效,紧急指针是一个正的偏移量,和序号字段中的值相加表示紧急数据最后一个字节的序号。
3)      LWIP中RAW API编程接口中与TCP相关的函数
LWIP提供了很多关于 TCP 的 RAW API 编程函数,我们可以使用这些函数来完成有关TCP的实验,我们在表 34.1.2列出了一部分函数。
表 34.1.2  TCP RAW API函数
lALPBF8a7TS3277NAarNA4Y_902_426.png

TCP连接由协议控制块(PCB)识别。有两种方法可以建立连接
1.       被动连接(服务端)
整个过程可分为以下几个步骤:
a)      调用tcp_new函数来创建一个pcb
b)      (可选)调用tcp_arg函数以将特定于应用程序的值与pcb相关联
c)      调用tcp_bind函数指定本地IP地址和端口
d)      调用tcp_listen函数或tcp_listen_with_backlog函数
e)      调用tcp_accept函数以指定新连接到达时要调用的函数
主动连接(客户端)
2.       调用tcp_new函数来创建一个pcb
a)      (可选)调用tcp_arg函数以将特定于应用程序的值与pcb相关联
b)      (可选)调用tcp_bind函数以指定本地IP地址和端口
c)      调用tcp_connect函数
1.2 实验任务
本章的实验任务是使用SDK软件自带的Lwip TCP perf Server模块了解TCP服务器的性能。
1.3 硬件设计
本章的硬件设计与前一章《基于lwip的echo server实验》相同,此处不再赘述。将《基于lwip的echo server实验》的Vivado工程另存为“lwip_tcp_server_perf”,打开SDK,进入软件设计。
1.4 软件设计
首先删除前一实验的工程。
在菜单栏中选择“File->New->Application Project”, 新建一个SDK应用工程。
在弹出的下图所示界面中,输入工程名“lwip_tcp_server_perf”,其它选项保持默认,点击“Next”。
    image006.jpg
图 34.4.1 配置工程
选择工程模版“lwIP TCP PerfServer”,然后点击“Finish”按钮,如图 34.4.2所示。
LwIP TCP PerfServer应用程序用于创建TCP服务器并使用轻量级IP堆栈(lwIP)测试下行链路性能。该应用程序将领航者开发板MAC地址设置为00:0a:35:00:01:02,默认使用DHCP获取动态IP地址,如果DHCP失败,则使用默认设置的静态IPv4地址192.168.1.10。应用程序在领航者开发板上创建TCP服务器并侦听TCP客户端的连接,一旦远程客户端与此服务器连接,TCP服务器将开始从客户端接收数据。客户端连接的详细信息和数据传输统计信息将由服务器在串行控制台上显示


image008.jpg
图 34.4.2 选择“lwip TCP Perf Server”模版
展开lwip_TCP_server应用工程目录下的src目录,可以看到很多平台相关的文件(主要是platform开头的文件)。为了方便分析,我们将src文件夹与本实验不相关的平台文件删除,删除后的src文件夹内容如下图所示:
   image009.png
图 34.4.3 删除后的src文件夹内容
该实验的main.c文件与《lwip echo server》实验的main.c基本相同,无实质性变化,由于在《lwip echo server》实验已讲解了main.c的内容,此处我们就不赘述了。本章我们重点关注的是lwip raw接口下tcp的使用,创建tcp服务器和测试性能主要在tcp_perf_server.c文件中实现。在讲解tcp_perf_server.c文件之前我们先来看一下当使用lwip作为TCP服务器时,会话的建立过程
由于raw TCP实现主要通过回调执行,因此其操作往往与各个消息的接收和处理密切相关。因此,熟悉底层TCP协议是有帮助的。对于没有lwIP使用经验的人来说,有时并不清楚什么时候需要调用什么。下表显示了远程客户端和本地lwIP tcp服务器之间交互的顺序图。
34.4.1 lwIP会话建立(远程客户端/本地lwIP服务器)
lALPBGKoa9mBcsbNArrNAyo_810_698.png

lALPBFf_7-sutmnNAfjNAyo_810_504.png

首先我们来看start_application函数,该函数在main函数中调用,后面的函数基本上都是通过该函数回调使用。start_application函数代码如下:
  1. void start_application(void)
  2. {
  3.      err_t err;
  4.      struct tcp_pcb *pcb, *lpcb;

  5.      //创建服务器PCB
  6.      pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);
  7.      if (!pcb) {
  8.          xil_printf("TCPserver: Error creating PCB. Out of Memory\r\n");
  9.          return;
  10.      }
  11.      //绑定端口号
  12.      err = tcp_bind(pcb, IP_ADDR_ANY, TCP_CONN_PORT);
  13.      if (err != ERR_OK) {
  14.          xil_printf("TCPserver: Unable to bind to port %d: "
  15.                  "err = %d\r\n" , TCP_CONN_PORT, err);
  16.          tcp_close(pcb);
  17.          return;
  18.      }

  19.      //将连接队列限制设置为1,以便一次为一个客户端提供服务
  20.      lpcb = tcp_listen_with_backlog(pcb, 1);
  21.      if (!lpcb) {
  22.          xil_printf("TCPserver: Out of memory while tcp_listen\r\n");
  23.          tcp_close(pcb);
  24.          return;
  25.      }

  26.      tcp_arg(lpcb, NULL);                //此处不需要回调函数的任何参数
  27.      tcp_accept(lpcb, tcp_server_accept);//指定用于传入连接的回调

  28.      return;
  29. }
复制代码
可以看到函数的调用与表 34.4.1中的“lwIP服务器操作”列的函数顺序一致。其中tcp_new_ip_type函数与我们在表 34.1.2中列的tcp_new函数有点区别,tcp_new_ip_type函数不仅具有tcp_new函数的功能,而且可以指定侦听的IP地址的类型,是用IPv4(IPADDR_TYPE_V4)、IPv6(IPADDR_TYPE_V6)还是两者都可以(IPADDR_TYPE_ANY),IPADDR_TYPE_ANY只有在lwip开启了IPv6功能才可以使用,本实验因为我们没有使能IPv6功能,所以tcp_new_ip_type函数的IPADDR_TYPE_ANY不起作用,此处调用该函数主要是考虑兼容性,如果只用IPv4,可以调用tcp_new函数。
tcp_bind函数用于绑定本地端口号和IP地址,IP_ADDR_ANY表示任意本地地址,TCP_CONN_PORT在tcp_perf_server.h头文件中宏定义为5001,该端口是我们后面使用的iperf工具的默认连接端口。
tcp_listen_with_backlog函数与tcp_listen函数的区别如下:

其中TCP_DEFAULT_LISTEN_BACKLOG为8位二进制的最大值0xff。由于本实验实现的功能是测试TCP的性能,所以此处将连接队列限制设置为1,以便一次为一个客户端提供服务。
tcp_accept函数用于设置接受(accept)回调函数tcp_server_accept。
从表 34.4.1可以看到,执行start_application函数后,客户端就可以发起连接,然后底层堆栈与客户端进行三次握手,握手成功后,调用接受回调,也就是调用tcp_server_accept函数,该函数代码如下:
  1. //用于服务器accept的回调函数
  2. static err_t tcp_server_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
  3. {
  4.      if ((err != ERR_OK) || (newpcb == NULL)) {
  5.          return ERR_VAL;
  6.      }
  7.      c_pcb = newpcb;             //保存连接的客户端PCB

  8.     //保存最终报告的开始时间
  9.      server.start_time = get_time_ms();
  10.      server.end_time = 0;        //ms
  11.      //更新连接的客户端ID
  12.      server.client_id++;
  13.      server.total_bytes = 0;

  14.      //初始化临时报告参数
  15.      server.i_report.report_interval_time = INTERIM_REPORT_INTERVAL * 1000;  //s
  16.      server.i_report.last_report_time = 0;
  17.      server.i_report.start_time = 0;
  18.      server.i_report.total_bytes = 0;

  19.      print_tcp_conn_stats();     //打印连接状态信息

  20.      //设置tcp rx连接的回调
  21.      tcp_arg(c_pcb, NULL);
  22.      tcp_recv(c_pcb, tcp_recv_perf_traffic);
  23.      tcp_err(c_pcb, tcp_server_err);

  24.      return ERR_OK;
  25. }
复制代码
该函数的主要作用是设置recv接收回调和错误中止回调。代码第174-184行用于初始化测试TCP性能的相关数据,INTERIM_REPORT_INTERVAL参数在tcp_perf_server.h中宏定义如下:
/*seconds between periodic bandwidth reports */
#defineINTERIM_REPORT_INTERVAL 5
该值代表每隔多长时间打印一次报告,也就是临时报告,此处的5代表5秒,当然也可以修改成其它值。
从表34.4.1可以看到,设置好tcp_server_accept的最后三个函数后,连接就正式建立了,这时候就可以互通有无了。此时如果客户端发起数据传输,lwip堆栈调用recv回调,也就是tcp_recv(c_pcb,tcp_recv_perf_traffic)函数中的tcp_recv_perf_traffic函数,该函数代码如下:
  1. //用于服务器recv的回调函数
  2. static err_t tcp_recv_perf_traffic(void *arg, struct tcp_pcb *tpcb,
  3.          struct pbuf *p, err_t err)
  4. {
  5.      if(p == NULL){
  6.          u64_t now =get_time_ms();
  7.          u64_tdiff_ms = now - server.start_time;
  8.         tcp_server_close(tpcb);
  9.         tcp_conn_report(diff_ms,TCP_DONE_SERVER);
  10.          xil_printf("TCPtest passed Successfully\n\r");
  11.          return ERR_OK;
  12.      }

  13.      server.total_bytes+= p->tot_len;               //记录最终报告的总字节数

  14.      if(server.i_report.report_interval_time){
  15.          u64_t now =get_time_ms();
  16.          server.i_report.total_bytes+= p->tot_len;  //记录临时报告的总字节数
  17.          if(server.i_report.start_time){
  18.              u64_tdiff_ms = now - server.i_report.start_time;
  19.              if(diff_ms >= server.i_report.report_interval_time){
  20.                 tcp_conn_report(diff_ms,INTER_REPORT);
  21.                  //重置临时报告计数器
  22.                 server.i_report.start_time =0;
  23.                 server.i_report.total_bytes= 0;
  24.              }
  25.          }else {
  26.              server.i_report.start_time= now;   //保存临时报告的开始时间
  27.          }
  28.      }

  29.      tcp_recved(tpcb,p->tot_len);

  30.      pbuf_free(p);
  31.      return ERR_OK;
  32. }
复制代码
由于本实验的功能是使用lwip测试TCP服务器的链路性能,测试的方法是接收客户端发来的数据流,对该数据流以每隔INTERIM_REPORT_INTERVAL时间统计一次客户端在该时间段内发送的数据总字节数,从而统计该段时间内的平均带宽,并打印该段时间内的临时报告。除此之外,还统计整个测试时间内的总字节数,从而统计整个测试时间内的平均带宽,并打印最终的测试报告。所以该函数的主要作用就是对接收到的数据进行处理。代码第149行调用的tcp_conn_report函数内容实现如下:
  1.   //TCP服务器会话的report函数
  2.   static void tcp_conn_report(u64_t diff,
  3.           enumreport_type report_type)
  4.   {
  5.       u64_t total_len;
  6.       double duration, bandwidth = 0;
  7.       chardata[16], perf[16],time[64];
  8.   
  9.       if(report_type == INTER_REPORT) {
  10.           total_len =server.i_report.total_bytes;
  11.       }else {
  12.           server.i_report.last_report_time= 0;
  13.           total_len =server.total_bytes;
  14.       }
  15.   
  16.       //将持续时间从毫秒转换为秒,带宽转换为比特/秒
  17.       duration =diff / 1000.0;   //secs
  18.       if(duration)
  19.           bandwidth =(total_len / duration) *8.0;
  20.   
  21.       stats_buffer(data,total_len, BYTES);
  22.       stats_buffer(perf,bandwidth, SPEED);
  23.       //在32位平台上,xil_printf无法打印u64_t值,因此在字符串中转换这些值并显示结果
  24.       sprintf(time,"%4.1f-%4.1f sec",
  25.               (double)server.i_report.last_report_time,
  26.               (double)(server.i_report.last_report_time+ duration));
  27.       xil_printf("[%3d]%s  %sBytes  %sbits/sec\n\r",server.client_id,
  28.               time,data, perf);
  29.   
  30.       if(report_type == INTER_REPORT)
  31.           server.i_report.last_report_time+= duration;
  32.   }
复制代码
该函数的主要作用是打印测试报告信息。代码第87行调用的stats_buffer函数的主要作用是进行数据换算,包括单位换算,如将bit数换算成合适的单位,如Mbit,其实现如下:
  1. static void stats_buffer(char* outString, double data, enum measure_t type)
  2. {
  3.       intconv = KCONV_UNIT;
  4.       constchar *format;
  5.       doubleunit = 1024.0;

  6.       if (type == SPEED)
  7.           unit = 1000.0;

  8.       while (data >= unit && conv <= KCONV_GIGA) {
  9.           data /= unit;
  10.           conv++;
  11.       }

  12.       if (data < 9.995) {         // 9.995四舍五入到10.0
  13.           format = "%4.2f %c";    // #.##
  14.       } else if (data < 99.95) {  //99.95四舍五入到100
  15.           format = "%4.1f %c";    // ##.#
  16.       } else {
  17.           format = "%4.0f %c";    // ####
  18.       }
  19.       sprintf(outString, format, data, kLabel[conv]);
  20. }
复制代码
注意代码第46-49行的unit数值的差异,当测试速度时,单位是1000,而不是统一的用1024,这在下载验证时会体现出来。
从表34.4.1可以看到,调用接收回调后,如果客户端需要请求数据的话就需要调用tcp_write()函数响应数据请求。本实验因客户端无数据请求,因此无需调用tcp_write()函数。tcp_recved()函数在接收回调函数tcp_recv_perf_traffic中实现,见代码第159行。
如果客户端结束连接,就根据代码第191行的tcp_err(c_pcb,tcp_server_err)函数; 调用错误/中止回调函数tcp_server_err,结束连接。tcp_server_err函数及其相关函数实现如下:
  1. //TCP服务器关闭会话
  2. static void tcp_server_close(struct tcp_pcb *pcb)
  3. {
  4.      err_t err;

  5.      if (pcb != NULL) {
  6.          tcp_recv(pcb, NULL);
  7.          tcp_err(pcb, NULL);
  8.          err = tcp_close(pcb);
  9.          if (err != ERR_OK) {
  10.              tcp_abort(pcb);
  11.          }
  12.      }
  13. }

  14. //错误回调,tcp会话中止
  15. static void tcp_server_err(void *arg, err_t err)
  16. {
  17.      LWIP_UNUSED_ARG(err);
  18.      u64_t now = get_time_ms();
  19.      u64_t diff_ms = now - server.start_time;
  20.      tcp_server_close(c_pcb);
  21.      c_pcb = NULL;
  22.      tcp_conn_report(diff_ms, TCP_ABORTED_REMOTE);
  23.      xil_printf("TCPconnection aborted\n\r");
  24. }
复制代码
可以看到tcp_server_err函数对接收到的客户端的数据做最后的处理,并调用tcp_server_close函数关闭会话。
至此,tcp_perf_server.c文件的主要代码内容就讲完了,接下来进行下载验证,看一下tcp服务器的链路性能。
1.5 下载验证
首先我们将下载器与领航者底板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用Mini USB连接线将USB UART接口与电脑连接,用于串口通信。使用网线一端连接领航者开发板的以太网接口,另一端与电脑或路由器连接。最后连接开发板的电源,并打开电源开关。
在SDK软件下方的SDK Terminal窗口中点击右上角的加号设置并连接串口。然后下载本次实验的elf文件。下载完成后,可以看到串口打印的结果。

image013.jpg
图 34.5.1 显示打印结果
从串口打印的倒数第二行可以看到,TCP服务器侦听的端口号为5001。最后一行是本实验的关键命令,用于测试TCP链路性能。此时我们需要一个测试的工具iperf。iperf是一种用于主动测量IP网络上可达到的最大带宽的工具。它支持调整与时序、协议和缓冲区相关的各种参数。对于每个测试,它报告测量的吞吐量/比特率、损耗和其它参数。利用 Iperf这一特性,可以用来测试一些网络设备如路由器、防火墙、交换机等的性能。
由于iperf是第三方工具,需要我们手动安装,可以在开发板随附的资料“6_软件资料/1_软件”中找到,名为iperf.exe即是,直接将iperf.exe复制到C:\Windows目录即可。
iperf常用参数列在下表:
lALPBFf_7-sxYI3NAbnNAnM_627_441.png
我们打开电脑的CMD(按win+r键后输入cmd),输入“iperf -c 192.168.1.10 -i 5 -t 30 -w2M”,如下图所示:

image014.png
34.5.2 进行iperf测试
该命令指示iperf以客户端模式启动,连接到服务器192.168.1.10,指定TCP窗口大小为2Mbyte(参数-w 2M), 测试30秒(-t 30),因为300秒太长,不方便截图,所以改为30秒,每隔5秒打印一次输出(-i 5)。
回车后,打印连接信息,并启动测试,如下图所示:
image016.jpg

34.5.3  iperf测试结果
可以看到,打印出来的测试信息分为四列,分别是ID、Interval、Transfer和Bandwidth。ID用于标识测试的连接,Interval是测试时间段,由于每隔5秒打印一次输出(-i 5),所以Transfer表示该时间段内传输的数据总量,Bandwidth为该时间段内的平均带宽。
由于只测试了30秒,可以看到该段时间内带宽稳定在946Mbits/sec,对于千兆网来说,是一个合理值。另外SDK的串口终端也打印出了信息,如下图所示:
image018.jpg

34.5.4 SDK打印iperf测试结果




正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

5

帖子

0

精华

新手入门

积分
17
金钱
17
注册时间
2019-2-25
在线时间
4 小时
发表于 2022-2-22 22:48:56 | 显示全部楼层
我用原子哥自带的程序,下载验证,串口打印信息无误,自动链接也是1:1000,但是iperf命令,提示无法链接,不知道是什么情况
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

新手入门

积分
9
金钱
9
注册时间
2022-4-30
在线时间
1 小时
发表于 2022-11-16 19:50:55 | 显示全部楼层
liuwenqiang 发表于 2022-2-22 22:48
我用原子哥自带的程序,下载验证,串口打印信息无误,自动链接也是1:1000,但是iperf命令,提示无法链接, ...

iperf 改成iperf3
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-11-23 09:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表