Github源码
多线程/进程问题:以iperf3为例 在给一个项目写可视化的时候,项目需要用iperf3来进行网络测试。 ipef3分为服务器server端和客户client端两个进程,一般使用cmd打开,开启测试的界面是这个样子:
server端 :
client端:
第一个坑 为了能够使用python代码控制控制台打开iperf3.exe,使用==subprocess==模块来启动。
但是subprocess直接启动程序,需要将iperf3.exe的路径加入到系统变量里,这样就不需要cmd进入对应文件目录再启动:
第二个坑 在解决直接用命令打开ipef3.exe之后,就是用subprocess使用iperf3.exe -s和iperf3.exe -c 127.0.0.1
这两个命令,应该这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def server (): with subprocess.Popen(["iperf3.exe" , "-s" ], stdout=subprocess.PIPE, universal_newlines=True ) as process: while True : print("doing" ) output = process.stdout.readline() if output == '' and process.poll() is not None : break if output: a=output.strip() rc = process.poll()
注意subprocess.Popen(["iperf3.exe", "-s"],
只有这样写,才是正确的输入参数的格式,将-s这个参数和前面分开!!!!!
第三个坑 虽然我现在能够启动server和client并且实现了iperf推流,但是在这两个线程退出之后,我的vscode调试界面居然没有退出!!
后来仔细想想,我是调用了个线程开启了iperf这个进程,因此虽然这次推流结束了但是iperf server服务进程还在,因此我还需要将这个进程退出才行:
1 2 3 4 5 6 7 8 9 if flag ==1 : print("client has shut" ) with subprocess.Popen("taskkill /IM iperf3.exe /F" , stdout=subprocess.PIPE, shell=True ,universal_newlines=True ) as process: while True : output = process.stdout.readline() if output == '' and process.poll() is not None : break if output: print(output.strip())
这样,我就输入cmd命令将进程关闭了hhhh。简单粗暴又好用:
感谢:雷学长
UDP报文解析 字符串与数组
bytearray操作用法
4字节数转化为浮点数
剩余任务:
汉字pygame可视化 链接
12.25 要干的活:
1.SV,只显示两个节点:white_check_mark:
2.三段组网,数据根据V段信息,(x,y,z)(x_speed,y_speed,z_speed)来排列:white_check_mark:
3.三段组网,拓扑连线根据S段信息:white_check_mark:
4.根据S选中了谁,就点亮谁
v段node1的yz坐标出现nan,应该不是我的问题
tkinter的使用 tkinter实现勾选和反选
下拉框
Tkinter组件
单选框
测试平台代码解析 文件结构
V段组网测试
product.py ==77行==
if条件内为判断点击到了“V段测试”
1 2 3 4 5 6 7 if (点击到了“V段测试”)print("click 1" ) BK_flag=2 S_flag=0 Ceshi_1.if_click = 1 Ceshi_2.if_click = 0 Ceshi_3.if_click=0
点击选择到V段之后,会点击测试客户端/测试服务器,下面以点击到服务器为例 ==102行==
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 if (测试服务器)print("click 4" ) node2.if_click = 1 node3.if_click = 0 Ceshi_4.if_click = 1 Ceshi_5.if_click = 0 Ceshi_6.if_click = 0 V_waiting_flag=1 if S_flag==0 : V_listen=Thread(target=api.V_config_server_receive, args=(api,)) V_listen.start() print('V is listening' ) time.sleep(1 ) V_send=Thread(target=api.V_config_server_send, args=(api,)) V_send.start()
这段代码做了两件事,V_listen线程监听了25600端口,准备接受板子配置好之后返还的UDP报文;随后等待2s,V_send向25600端口发送配置报文:
看看V_send线程启的函数:
1 2 3 4 5 6 7 8 9 def V_config_server_send (self ): port=25600 text2=b'给节点2发送的配置报文内容' text3=b'给节点3发送的配置报文内容' sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.sendto(text2, ('192.168.3.2' , port)) sock.sendto(text3,('192.168.3.3' ,port)) print("已发送" )
再看看V_listen线程启的函数:
1 2 3 4 5 6 7 8 9 10 11 def V_config_server_receive (self ): port=11000 port=25600 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('0.0.0.0' , port)) data, address = sock.recvfrom(1024 ) time.sleep(2 ) self.V_num=1 self.V_if_iperf=1 self.V_iperf_server(self)
注意在sock.recvfrom(1024)函数之后,即收到了板子回复报文之后,执行了self.V_iperf_server(self) 函数,这是在配置好了之后,开启iperf的server端。
看看这个V_iperf_server函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 def V_iperf_server (self ): fontObj = pygame.font.Font(self.ttf_abs, 17 ) if 'Windows' in platform.platform(): print('This platform is Windows' ) with subprocess.Popen(["iperf-2.1.0-rc-win.exe" ,"-s" ,"-u" ,"--port" ,"24600" ,"-i" ,"2" ], shell=True ,stdout=subprocess.PIPE, universal_newlines=True ) as process: while True : output = process.stdout.readline() if output == '' and process.poll() is not None : break if output: self.render.append(fontObj.render(output.strip(), False , (0 , 0 , 0 ))) if len (self.render)>6 : del self.render[0 ]
iperf server端在接收到iperf的信息之后,暂存为output,然后转化成字体格式保存在self.render 列表中
(iperf 的client端原理一样,不用赘述)
三节点组网 ==95==行,点击到“三节点组网”,BK_flag=3,第三个界面
==46行,开局就打开监听==
1 2 server = Thread(target=remote.pipe_begin, args=(remote,)) server.start()
执行Remote.py中的remote类中的pipe_begin函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 def pipe_begin (self ): parent_conn, child_conn=Pipe() fa= multiprocessing.Process(target=self.UDP_test_server, kwargs={'self' :self,'pipe' :child_conn}) fa.start() flag=1 while True : temp = parent_conn.recv() temp=temp.split() if flag==1 : self.Pitch_angle = temp[0 ] self.Yaw_angle=temp[1 ] self.Roll_angle = temp[2 ] if self.s_node1=='1' and self.s_node2=='1' : self.Nighbour_v["12" ]=1 self.Nighbour_s["12" ]=1 if self.s_node1=='1' and self.s_node3=='1' : self.Nighbour_v["13" ]=1 self.Nighbour_s["13" ]=1 if self.s_node3=='1' and self.s_node2=='1' : self.Nighbour_v["23" ]=1 self.Nighbour_s["23" ]=1 flag+=1 elif flag==2 : flag+=1 elif flag==3 : flag==1
UDP_test_server函数是执行了UDP_test.py文件中的server函数,
UDP_test.py中 的server函数:
1 2 3 4 5 6 7 def server (port ): sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind(('0.0.0.0' , port)) while True : data, address = sock.recvfrom(1024 ) node_data(data)
node_data()#报文解析函数就是将报文中的各字段解析出来,然后print出来那些数据:
1 2 3 4 5 print(Pitch_angle_s, Yaw_angle_s, Roll_angle_s, Node_x_s, Node_y_s, Node_z_s, Node_x_speed_s, Node_y_speed_s, Node_z_speed_s, Node1_id, Node2_x_s, Node2_y_s, Node2_z_s, Node2_x_speed_s, Node2_y_speed_s, Node2_z_speed_s, Node2_id, Node3_x_s, Node3_y_s, Node3_z_s, Node3_x_speed_s, Node3_y_speed_s, Node3_z_speed_s, Node3_id, now_node,s_info['node1' ]['id' ],s_info['node2' ]['id' ],s_info['node3' ]['id' ])
这些数据被print到了管道里,被Remote.py中的pipe_begin()函数接受并保存到self中的变量里
显示部分 主要讲==190行==之后的内容:
1 2 3 4 5 6 7 8 9 if api.render != []: loding_flag=0 for i in range (len (api.render)): screen.blit(api.render[i], (460 , 470 + 23 * i)) elif loding_flag==1 : font_loding = pygame.font.Font(api.ttf_abs, 30 ) text_big1 = font.render("配置中" , 1 , (255 , 10 , 10 )) screen.blit(text_big1,(700 ,500 ))
这是判断是否在配置中,如果配置结束了,开始iperf了,那么api.render变量中就会保存iperf的信息,然后就会依次显示出来:screen.blit(api.render[i], (460, 470 + 23 * i))
==222行==,在发送配置UDP报文,但是还没有收到板子的回复时,显示“等待回复中”字样
1 2 3 4 5 6 7 8 if len (api.render)>=3 : V_waiting_flag=0 elif V_waiting_flag==1 : pygame.draw.rect(screen,[200 ,200 ,200 ],[570 ,220 ,250 ,120 ],0 ) font_loding = pygame.font.Font(api.ttf_abs, 30 ) text_big1 = font.render("等待回复中" , 1 , (0 , 0 , 0 )) screen.blit(text_big1,(600 ,250 ))
242行到258行是根据节点的信息,判断节点该不该点亮,255行则是在修改邻接矩阵,决定后面的连线情况
261行 为画出连线
380到388行,为显示那几个大字
390行 为刷新屏幕,因为pygame的逻辑,这是一个整个的大循环,每个循环之后都需要刷新一遍元素,重新显示
391行可以看作是屏幕刷新率
学长加油:smiley: