前言

最近做了一个小软件,记录一下相关内容。

已有条件

现在已有一个硬件设备作为客户端(暂称其为“电路”)。

基于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/#

https://natapp.cn/article/natapp_newbie

PyQt5

pyqtgraph


作者:@臭咸鱼

转载请注明出处:https://www.cnblogs.com/chouxianyu/

欢迎讨论和交流!


使用Python语言通过PyQt5和socket实现UDP服务器的更多相关文章

  1. socket编程 ------ UDP服务器

    void vLANcommunication( void *pvParameters ) { int32 listenfd; do{ listenfd = socket(AF_INET, SOCK_D ...

  2. google的python语言规范

    Python语言规范   Lint Tip 对你的代码运行pylint 定义: pylint是一个在Python源代码中查找bug的工具. 对于C和C++这样的不那么动态的(译者注: 原文是less ...

  3. Python Web学习笔记之socket套接字

    套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象.它们允许程序接受并进行连接,如发送和接受数据.为了建立通信通道,网络通信 ...

  4. python 网络编程 TCP/IP socket UDP

    TCP/IP简介 虽然大家现在对互联网很熟悉,但是计算机网络的出现比互联网要早很多. 计算机为了联网,就必须规定通信协议,早期的计算机网络,都是由各厂商自己规定一套协议,IBM.Apple和Micro ...

  5. 部署基于python语言的WEB发布环境

    一.部署说明 1.python语言介绍 python简介 2.实验环境 实验机器:Vmware虚拟机 8核10G 网卡:桥接模式 系统:centos7.5 防火墙:关闭 Selinux:关闭 网段:1 ...

  6. Python 语言规范

    Python 语言规范 pychecker  对你的代码运行pychecker 定义: pychecker 是一个在Python 源代码中查找bug 的工具. 对于C 和C++这样的不那 么动态的( ...

  7. 【学习笔记】PYTHON语言程序设计(北理工 嵩天)

    1 Python基本语法元素 1.1 程序设计基本方法 计算机发展历史上最重要的预测法则     摩尔定律:单位面积集成电路上可容纳晶体管数量约2年翻倍 cpu/gpu.内存.硬盘.电子产品价格等都遵 ...

  8. Python 语言规范(Google)

    Python语言规范 Lint tip 对你的代码运行pylint 定义: pylint是一个在Python源代码中查找bug的工具. 对于C和C++这样的不那么动态的(译者注: 原文是less dy ...

  9. 关于《selenium2自动测试实战--基于Python语言》

    关于本书的类型: 首先在我看来技术书分为两类,一类是“思想”,一类是“操作手册”. 对于思想类的书,一般作者有很多年经验积累,这类书需要细读与品位.高手读了会深有体会,豁然开朗.新手读了不止所云,甚至 ...

随机推荐

  1. 访问控制列表与SSH结合使用,为网络设备保驾护航,提高安全性

    通过之前的文章简单介绍了华为交换机如何配置SSH远程登录,在一些工作场景,需要特定的IP地址段能够SSH远程访问和管理网络设备,这样又需要怎么配置呢?下面通过一个简单的案例带着大家去了解一下. 要实现 ...

  2. Ethical Hacking - Web Penetration Testing(9)

    SQL INJECTION Discovering SQLi in GET Inject by browser URL. Selecting Data From Database Change the ...

  3. awesome : vue-awesome 按需引入

    其实挺简单的,被文档带到沟里去了. main.js: 首先讲一下全部引入,很简单. import 'vue-awesome/icons' import Icon from 'vue-awesome/c ...

  4. 设计模式:memento模式

    目的:在不破坏系统封装性的前提下,记录系统每一步的状态,可以做到状态回退和前进 方法: 定义一个数据类,保存所有相关数据 定义一个管理类,提供保存和恢复的接口 具体操作类调用管理类的保存和恢复接口 例 ...

  5. humlbe bundle如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器?

    一般点账户名——设置——安全设置中开通虚拟MFA两步验证 具体步骤见链接 humlbe bundle如何绑定二次验证码_虚拟MFA_两步验证_谷歌身份验证器? 二次验证码小程序于谷歌身份验证器APP的 ...

  6. ‘100%’wuxiao

    有时候设置控件的width:’100%‘无效,  群友解释, 因为父控件的大小要靠自空间撑起来,确定    ??????

  7. 深入剖析.NETCORE中CORS(跨站资源共享)

    前言 由于现代互联网的飞速发展,我们在开发现代 Web 应用程序中,经常需要考虑多种类型的客户端访问服务的情况:而这种情况放在15年前几乎是不可想象的,在那个时代,我们更多的是考虑怎么把网页快速友好的 ...

  8. SQL语法分类

    数据查询 语法格式 : select [ , ...] from table_reference [ , ...] 去重复值 distinct关键字 , 从select结果集中删除所有重复的行,使结果 ...

  9. 国外的非常好的开发提问回答的网站https://stackoverflow.com/questions

    https://stackoverflow.com/questions 可以进行搜索,在页面顶部,有搜索输入框

  10. sublimeCLang配置报错以及sublime快捷键

    subimeClang需要手动配置我真的真的很服 记录一下满是报错的高光时刻 -------- 不过这个问题刚刚解决了 只要把所有的shared_ptr改成std::shared_ptr 就行 说白了 ...