当前位置:网站首页>【编程实践/嵌入式比赛】嵌入式比赛学习记录(一):TCP服务器和web界面的建立
【编程实践/嵌入式比赛】嵌入式比赛学习记录(一):TCP服务器和web界面的建立
2022-04-23 06:32:00 【PlusE Lin】
0. 前言
最近找同学参加了嵌入式比赛,为了让自己的简历不显得一穷二白,可惜我本人是计算机专业的学生,因此大部分的工作是上位机开发,可能也会搞一下WIFI模块。
由于在此过程中还是学到了一些东西,因此我打算以博客的形式记录之,以便后续浏览,也希望大家可以从我的博客中有所收获。
本人争取按时更新。
1. 本次任务介绍
目前接到的需求是上位机使用Web界面(最早的设想是GUI),将下位机传来的数据接收(使用TCP传输,后续可能改为UDP),并做处理后放到web网页上。因此我需要的工作是:
1.TCP server的建立(上位机做服务器,下位机做客户端)
2. Web界面的实现
3. TCP server向web server发送数据。
考虑到本人贫瘠的编程能力和web开发的需求,因此我打算使用Python开发。
TCP server使用socket库实现,web界面使用flask实现,通信则用requests由TCP server向web server的指定URL发送POST请求实现。
以下我将会介绍具体内容
2. TCP server的建立
Python中,可以使用socket库构建TCP server。
本人使用的是socketserver模块,其实也是基于socket的,使用这个模块的好处是可以更加方便的建立TCP server,甚至省去了创建时的绑定IP端口,调用accept阻塞的方法。
调用时的方法如下:
# 建立TCP server
def start_TCP(host,port):
myserver=socketserver.ThreadingTCPServer((host,port),MyHandler)
print("You have start server,address is: {}:{}".format(host,port))
#持续服务
myserver.serve_forever()
我们注意到,在构造类ThreadingTCPServer时的第二个参数是MyHandler,这个是自定义的类,继承了socketserver.BaseRequestHandler类,需要重写handle函数,具体如下:
class MyHandler(socketserver.BaseRequestHandler):
def handle(self):
while True:
#接收数据,处理
data=self.request.recv(1024)
try:
data=data.decode("gbk")
except:
#主要是防止编码错误问题
data="cannot show normally!"
#稍作包装
object={
"data":time.strftime("%Y-%m-%d %H:%M:%S",time.localtime())+" "+data}
#没有接收到数据,不向web server转发
if not data:
break
else:
#本来打算做成线程间通信的,后来一想是web server,直接发post请求好了
print("Got: {}".format(data))
self.request.send("You have successfully sent data!".encode("ascii"))
with requests.post("http://192.168.71.1:5000/",json=object) as r:
pass
具体的处理过程是:
- 调用self.requests.recv,接收数据,参数为接收长度
- 对数据进行处理,可以调用self.request.send向客户端回送消息
至于向web server转发的内容,后文会介绍。
3. Flask web的建立
flask是一个开源web框架,学起来非常简单,只要有一定的web基础(甚至是常识)就能学会。
具体的代码如下:
from flask import *
import threading
app=Flask(__name__)
#一些全局变量
messages=[]
length=0
#主页面
@app.route("/",methods=["GET","POST"])
def index_page():
global messages
#接收TCP server发送的数据
data=request.get_json()
#若有数据,则相应操作,这里是加入到全局列表中
if data is not None:
messages.append(data["data"])
#渲染模板
return render_template("index0.html",messages=messages)
#ajax会向此路由发送post请求轮询,用于异步更新路由
@app.route("/get_data",methods=['GET','POST'])
def get_data():
#发现有新数据加入的时候,要求前端进行相应动作,例如更新路由
global length
if(length<len(messages)):
length=len(messages)
return "flash"
return ""
其中前端代码如下
首先是index0.html,因为是学习部分,就放了几个数据
<html>
<head>
</head>
<body>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<script type="text/javascript" src="{
{url_for('static', filename = 'js/update.js')}}"></script>
<h2>历史信息</h2>
{% for each in messages %}
<p>{
{each}}</p><br>
{% endfor %}
</body>
</html>
这是比较简单的flask模板的编写,这里不再进行叙述。
然后是用到的JavaScript代码。很抱歉,本人对js并不熟悉,这些代码也是从网上找+自己改的,因此不能给出具体的解释。
var script=document.createElement("script");
script.type="text/javascript";
script.src="jquery.js";
//ajax轮询,每100ms调用一次函数,即ajax请求
setInterval(
function(){
$.ajax({
url:"/get_data",
async:true,
type:'post', //貌似post才行,我很疑惑
timeout:10000,
success:function(data){
if(data=="flash"){
//your operation
window.location.reload();//刷新路由,也可以是其他操作
}
},
error:function(xhr,type){
window.alert("error!");
}
})
},100
)
4. TCP server 向web server通信
这里就用到了一行,即requests.post请求
并且前面也已经展示了
# 本实验中,web server的ip和端口为192.168.71.1:5000
with requests.post("http://192.168.71.1:5000/",json=object) as r:
pass
5. 总程序
总程序用来启动web server和TCP server,由于两个server都是持久服务,因此在主进程中启动一个就会陷入死循环,不能启动另一个,因此我将这两个服务器启动放到了两个线程上,并且设置了不同的端口号防止冲突。
(其实这里我一直陷入困惑,因为按照我浅显的计网知识,我觉得两个server应该在两个进程上,可放到两个线程上貌似也可以,反而是多进程失败了……后续有时间会探求一下)
### index.py
from flask import *
import threading
import socketserver
import time
# web服务器部分
from app_views import *
#TCP服务器部分
from lib.MyServer import *
def start_TCP(host,port):
myserver=socketserver.ThreadingTCPServer((host,port),MyHandler)
print("You have start server,address is: {}:{}".format(host,port))
myserver.serve_forever()
def start_flask(host,port):
print("you have start flask server,address is: {}:{}".format(host,port))
app.run(host=host,port=port)
def main():
th1=threading.Thread(target=start_flask,args=("192.168.71.1",5000))
th2=threading.Thread(target=start_TCP,args=("192.168.71.1",5001))
th1.start()
th2.start()
if __name__=="__main__":
main()
6.验收
启动上述代码,打开网络调试助手,向192,168.71.1:5001发送数据,可以看到在前端已正常显示,证明实验成功。


7. 可改进的地方
- 可不可以直接向web server发送数据?我不好说,因为感觉还是要建立TCP连接才行
- 有没有其他转交方式?可以线程间共享变量,使用信号量控制发送接收关系,但可能很麻烦
- 前端更新数据除了ajax轮询还有没有更好的方式?可不可以实现真正的异步通讯,以免不必要的负载?
本篇文章到此,感谢收看!
版权声明
本文为[PlusE Lin]所创,转载请带上原文链接,感谢
https://blog.csdn.net/m0_51274130/article/details/124203782
边栏推荐
- Using lambda expression to solve the problem of C file name sorting (whether it is 100 or 11)
- The projection vector of a vector to a plane
- 平面定义-平面方程
- strcat()、strcpy()、strcmp()、strlen()
- Houdini > fluid, rigid body export, learning process notes
- Internal network security attack and defense: a practical guide to penetration testing (8): Authority maintenance analysis and defense
- CTF-MISC学习之从开始到放弃
- BUUCTF MISC刷題
- 内网渗透系列:内网隧道之pingtunnel
- 第四章 无形资产
猜你喜欢

庄懂的TA笔记(七)<Lambert+Phong+Shadow+3EvColor+AO>

【Unity VFX】VFX特效入门笔记-火花制作

Teach-Repeat-Replan: A Complete and Robust System for Aggressive Flight in Complex Environments

《内网安全攻防:渗透测试实战指南》读书笔记(八):权限维持分析及防御

关于U盘数据提示RAW,需要格式化,数据恢复笔记

ABAP ALV显示金额与导出金额不一致

Intranet penetration series: icmpsh of Intranet tunnel

SAP STO With Billing流程与配置

The displayed amount of ABAP ALV is inconsistent with the exported amount

Shapley Explanation Networks
随机推荐
How does Apache Hudi accelerate traditional batch mode?
MySQL in window10 version does not work after setting remote access permission
IDEA快捷键
RGB color to hex and unit conversion
SAP STO With Billing流程与配置
Houdini>流体,刚体导出学习过程笔记
索引被锁数据无法写入ES问题处理
How does Apache Hudi accelerate traditional batch mode?
【Unity VFX】VFX特效入门笔记-火花制作
A programmer who works four hours a day
Mysql database backup and recovery under Linux (full + incremental)
KCD_EXCEL_OLE_TO_INT_CONVERT报错SY-subrc = 2
SAP TR手动导入系统操作手册
SAP GUI安全性
SAP tr manual import system operation manual
ABAP ALV显示金额与导出金额不一致
Nodejs (VI) sub process operation
About USB flash drive data prompt raw, need to format, data recovery notes
Zhuang understand's TA notes (VI) < fakeenvreflect & rust, rust effect >
内网渗透系列:内网隧道之icmptunnel(DhavalKapil师傅的)