使用Python语言通过PyQt5和socket实现UDP服务器
前言
最近做了一个小软件,记录一下相关内容。
已有条件
现在已有一个硬件设备作为客户端(暂称其为“电路”)。
基于SIM卡,电路可以通过UDP协议传输数据(程序已经内置在电路中),只需要修改配置文件(位于SD卡中,主要修改服务器端的IP和端口)即可。
需求
我面向的需求是这样的:我需要开发一个服务器端的程序,接收多个客户端发来的数据并开发可视化界面。
总结
从开发角度和技术角度来看,软件的基础和核心技术是使用UDP协议进行数据传输,并使用PyQt5和pyqtgraph做可视化界面(还用到了QThread和自定义的下拉复选框),开发过程中还涉及到了内网穿透和NATAPP。
理论基础:运输层
为使用UDP协议进行数据传输,我大致复习了一下计算机网络中的运输层。
功能
运输层实现两台主机中进程之间的通信,一个主机中的多个进程可以和另一台主机中的多个进程通信。
运输层实现上述功能的方案是端口(port)
两个主要协议
运输层有两个主要协议:
- 传输控制协议TCP(Transmission Control Protocol)
- 用户数据报协议UDP(User Datagram Protocol)
TCP
- TCP是面向连接的
- 应用进程在传输数据前必须先建立连接,数据传送结束后要释放连接
- TCP连接是点对点的
- 每一条TCP连接只能有两个端点
- TCP不提供广播或多播服务
- TCP提供可靠交付的服务
- 通过TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达
- TCP面向字节流
- 虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序交下来的数据仅仅看成一连串的无结构的字节流。
- TCP不保证接收方应用程序所收到的数据块和发送方应用程序所发出的数据块具有对应大小
- TCP保证接收方应用程序收到的字节流必须和发送方应用程序发出的字节流完全一样,同时接收方应用程序必须有能力识别收到的字节流,把它还原成有意义的应用层数据
UDP
- UDP是无连接的
- 在传输数据前不需要先建立连接,主机在收到UDP报文后不需要给出任何确认
- UDP是面向报文的
- 发送方:UDP对应用层交下来的报文,不合并也不拆分,添加首部后就交付给IP层
- 接收方:UDP对IP层交上来的UDP用户数据包,在去除首部后就直接交付给应用层的进程
- UDP尽最大努力交付
- 不保证可靠交付
- UDP支持一对一、一对多、多对一和多对多的交互通信
Python中的UDP编程
Python中的UDP编程可以通过socket来实现,下面是一个简单样例
服务器端
import socket
server_ip = '127.0.0.1'
server_port = 9999
# 建立套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # socket.SOCK_DGRAM代表是UDP通信
# 绑定IP和端口
s.bind((server_ip, server_port))
print('Bind UDP Server on %s:%s' % (server_ip, server_port))
while True:
# 接收数据
data, addr = s.recvfrom(1024)
print(addr, "\t", data)
# 发送数据
s.sendto(b'Received:%s'%data, addr)
客户端
import socket
server_ip = '127.0.0.1'
server_port = 59955
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # socket.SOCK_DGRAM代表是UDP通信
for data in [b'Michael', b'Tracy', b'Sarah']:
# 发送数据
s.sendto(data, (server_ip, server_port))
# 接收数据
# print(s.recv(1024).decode('utf-8'))
s.close()
值得注意的问题:缓冲区机制
UDP通信时,两个主机都要建立一个socket。
我这里的情况是客户端会一直给服务器端发数据。
在服务器端我发现socket一旦建立(准确来讲是创建socket对象并绑定至本地端口),就会一直接收数据,而不是调用recvfrom等函数(这类函数用来接收数据)时才会接收。
估计这是缓冲区机制,UDP应该就是这么设计的。大概就是socket对象创建后,收到的内容就会放入缓冲区,如果调用了recvfrom等数据接收函数就从缓冲区中取出数据。
内网穿透
为什么要用内网穿透
先不讲内网穿透是什么,有兴趣的可以自己去查查,下面我大概讲讲我浅显的理解。
在开发服务器端程序的过程中,我用的是自己的电脑,连接的网络是手机热点(因为在宿舍),因此我的电脑是没有公网IP的。
客户端程序用的是SIM卡,用的是公网(外网)IP,我开发的服务器端程序用的是私网(内网)IP。
公网IP是无法访问私网IP的(因为NAT),所以我需要让我的服务器端程序能够被外网访问。
问了一下@roadwide,他说要用内网穿透,并推荐了NATAPP等软件。
NATAPP的使用
怎么用呢?看看官方教程就知道了,链接放在文章末尾了。
讲一个比较关键的点,以理解下NATAPP是干嘛的

NATAPP运行起来后,就会将上图红框里的URL映射到本机(127.0.0.1)的80端口。
NATAPP会给我一个URL(作为我的外网IP),这样客户端程序通过访问NATAPP给我的URL就可以间接访问我在本机运行的服务器端程序。
PyQt5
QThread
服务器端程序的界面上有两个作用分别是开始接收数据和停止接收数据的按钮。
接收数据是通过一个while循环(循环体中接收一个数据)实现的,如果点击开始接收数据的按钮,那就运行while循环直到停止接收数据的按钮被点击。
刚开始实现数据接收功能时发现程序界面会崩溃、点击不动,因为直接把while循环写在软件主界面的代码中。
后来使用了PyQt5中的QThread(也有人说QThread并不是一个线程),在一个线程中实现while循环,然后就成功了。
在实现时我参考了其他网友的代码,参考链接放在文章末尾,注意一点是实现方式不止一种,比如说有些网友说用threading也可以,而且我也发现我的思路和参考的那份代码稍有不一样(我们实现的功能是相似的,但我只用了一个pyqtSignal,而那位网友用了两个)。
下拉复选框
这个软件需要有一个下拉复选框,而PyQt5中并没有这个东西,因此需要手动实现,这里我参考了其他网友的实现方式,参考链接见文章末尾。
参考链接
Python中的UDP编程
https://blog.csdn.net/vict_wang/article/details/81587093
https://www.jb51.net/article/165933.htm
理解NAT和内网穿透
https://baike.baidu.com/item/nat/320024
https://baike.baidu.com/item/内网穿透
NATAPP
https://natapp.cn/article/natapp_newbie
PyQt5
PyQt5下拉式复选框QComboCheckBox
QThread实现循环
https://segmentfault.com/a/1190000020746912?utm_source=tag-newest
AttributeError: 'PyQt5.QtCore.pyqtSignal' object has no attribute 'connect'
pyqtgraph
pyqtgraph中绘制多个线条(我实现这个功能时也看了pyqtgraph的example)
pyqtgraph中添加图例(legend)
作者:@臭咸鱼
转载请注明出处:https://www.cnblogs.com/chouxianyu/
欢迎讨论和交流!
使用Python语言通过PyQt5和socket实现UDP服务器的更多相关文章
- socket编程 ------ UDP服务器
void vLANcommunication( void *pvParameters ) { int32 listenfd; do{ listenfd = socket(AF_INET, SOCK_D ...
- google的python语言规范
Python语言规范 Lint Tip 对你的代码运行pylint 定义: pylint是一个在Python源代码中查找bug的工具. 对于C和C++这样的不那么动态的(译者注: 原文是less ...
- Python Web学习笔记之socket套接字
套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象.它们允许程序接受并进行连接,如发送和接受数据.为了建立通信通道,网络通信 ...
- python 网络编程 TCP/IP socket UDP
TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...
- 部署基于python语言的WEB发布环境
一.部署说明 1.python语言介绍 python简介 2.实验环境 实验机器:Vmware虚拟机 8核10G 网卡:桥接模式 系统:centos7.5 防火墙:关闭 Selinux:关闭 网段:1 ...
- Python 语言规范
Python 语言规范 pychecker 对你的代码运行pychecker 定义: pychecker 是一个在Python 源代码中查找bug 的工具. 对于C 和C++这样的不那 么动态的( ...
- 【学习笔记】PYTHON语言程序设计(北理工 嵩天)
1 Python基本语法元素 1.1 程序设计基本方法 计算机发展历史上最重要的预测法则 摩尔定律:单位面积集成电路上可容纳晶体管数量约2年翻倍 cpu/gpu.内存.硬盘.电子产品价格等都遵 ...
- Python 语言规范(Google)
Python语言规范 Lint tip 对你的代码运行pylint 定义: pylint是一个在Python源代码中查找bug的工具. 对于C和C++这样的不那么动态的(译者注: 原文是less dy ...
- 关于《selenium2自动测试实战--基于Python语言》
关于本书的类型: 首先在我看来技术书分为两类,一类是“思想”,一类是“操作手册”. 对于思想类的书,一般作者有很多年经验积累,这类书需要细读与品位.高手读了会深有体会,豁然开朗.新手读了不止所云,甚至 ...
随机推荐
- Mobilenet V1
目录 1. Depth Separable Convolution 2. 网络结构 3. 宽度因子和分辨率因子 4. 代码实现 参考博客: https://cuijiahua.com/blog/201 ...
- css:实现文本两行或多行文本溢出显示省略号
div{ display: -webkit-box; -webkit-box-orient: vertical; word-break: break-all; word-wrap: break-wor ...
- web自动化 -- ActionChains()的鼠标操作
webdriver模块下的ActionChains类 一.两个主要组件 1.实例化 ActionChains() 2.ActionChains(driver).perform() perform() ...
- Spring Security 实战干货:理解AuthenticationManager
1. 前言 我们上一篇介绍了UsernamePasswordAuthenticationFilter的工作流程,留下了一个小小的伏笔,作为一个Servlet Filter应该存在一个doFilter实 ...
- 如何消灭飞机的“黑色十分钟”,AI来帮忙
近年来,“AI的应用和落地”逐渐成了具化的关键词,它和很多事物很多行业结合在一起,形成了奇妙的“化学反应”.例如,在日常生活中,AI可以推送我们喜欢的新闻或视频,可以在拍照的时候识别场景提升照片的美感 ...
- MySQL组复制MGR(二)-- 组复制搭建
(一)主机操作 (1)路由信息vmnet5 192.168.10.0 (2)主机信息 主机名称 IP地址 操作系统版本 数据库版本 mgr-node1 192.168.10.11 centos 7.4 ...
- Bug--Mybatis报错:There is no getter for property named 'id' in 'class java.lang.Integer'
Mybatis 添加@Param("")注释就可以了
- HTML基础和标签
HTML 1.属性 在开始标签中写的键值对 2.颜色 ①英文 ②16进制代码 例如: #cccccc #ccc (缩写) #000000 ③Rgba(0~255,255,255,0~1) 0~1代 ...
- PHP import_request_variables() 函数
import_request_variables() 函数将 GET/POST/Cookie 变量导入到全局作用域中.该函数在最新版本的 PHP 中已经不支持.高佣联盟 www.cgewang.com ...
- PHP simplexml_load_file() 函数
实例 转换 XML 文件为 SimpleXMLElement 对象,然后输出对象的键和元素: <?php高佣联盟 www.cgewang.com$xml=simplexml_load_file( ...