前言

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

已有条件

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

基于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. Burp Suite Report - 报告功能

    1. 通过点击Host选择不同的颜色,可以设置严重性: 2.生成网页版应用分析报告:选中所有条目->右击网址,保存所有选中项目,存储格式为html.

  2. Ethical Hacking - NETWORK PENETRATION TESTING(5)

    Deauthentication Attacks Theory This attack is used to disconnect any device from any network within ...

  3. 【原创】linux设备模型之kset/kobj/ktype分析

    背 景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本 ...

  4. 仔细想想SpringAOP也不难嘛,面试没有必要慌

    文章已托管到GitHub,大家可以去GitHub查看阅读,欢迎老板们前来Star! 搜索关注微信公众号 码出Offer 领取各种学习资料! LOGO SpringAOP 一.什么是AOP AOP(As ...

  5. 用x种方式求第n项斐波那契数,99%的人只会第一种

    大家好啊,我们又见面了.听说有人想学数据结构与算法却不知道从何下手?那你就认真看完本篇文章,或许能从中找到方法与技巧.     本期我们就从斐波那契数列的几种解法入手,感受算法的强大与奥妙吧. 原文链 ...

  6. js 绑定的键盘事件

    在全局绑定键盘事件 document.onkeydown = function(event){        //在全局中绑定按下事件 var e  = event  ||  window.e; va ...

  7. Flutter获取远程数据 刷新UI界面

    import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; void main() => r ...

  8. vue学习(十八)使用自定义指令 为字体渲染颜色

    <div id="app"> //v-color 是自定义的 <input type="text" class="form-cont ...

  9. Java面试必问:ThreadLocal终极篇 淦!

    点赞再看,养成习惯,微信搜一搜[敖丙]关注这个互联网苟且偷生的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列 ...

  10. NanoHTTPD服务

    需要导入nanohttpd2.3,jar包 继承NanoHTTPD public class HttpServer extends NanoHTTPD { public HttpServer(int ...