Python網路程式設計 遠端更新STM32APP程式

2021-08-03 09:54:40 字數 4174 閱讀 3494

工具:stm32zet6和sim800c模組(客戶端),乙個可以上網的sim卡,乙個有外網的電腦(伺服器端)。

在了解socket通訊之前,需要了解一下什麼是tcp協議。tcp/ip事實上是一些協議(protocols)的合集。當前大多數使用中的通訊都是使用tcp協議。為了實現共享,tcp是通過把需要傳送的資料流分解為很多小資訊包在internet上傳輸的,而這些資訊包到了接收者的地方會再次合成在一起。通過分解成小的資訊包,其他程式的資訊包也可以同時被傳送。

tcp需要遠端識別機器,每台機器都有乙個唯一的ip的位址,通過埠號可以知道是這台電腦的哪個程式在傳送和接收資訊包。所以每個tcp連線的端點是由乙個ip位址和乙個埠號來唯一標識的。

tcp是乙個可靠的協議,除非整個網路出了問題,資料將完好的正確的傳輸到另一端。

此外還有udp也被廣泛的使用,經常被用來從乙個系統向其他系統傳送非常短的訊息。只能保證接收到的資料是完整的,udp比tcp低階,即不能保證資料是否真的能被接收到,也不能保證資料是不是只接收一次,還不能保證接收到的資訊次數是否和傳送時候的一致,但是優點是,由於它不能提供上面的那些保證,所以比tcp低階,tcp建立和關閉連線要花費時間,而udp對連線沒有什麼概念,不存在花費時間建立和關閉連線的問題。

對於我們的問題,需要可靠的資料傳輸,而且需要傳輸大量的資料,所以需要選擇tcp協議。

在網路程式設計中的乙個基本元件就是套接字(socket)。套接字基本上是兩個端點的程式之間的「資訊通訊」。在python中的大多數網路程式設計都隱藏了socket模組的基本細節,不直接和套接字互動。

套接字包括伺服器套接字和客戶機套接字。對於我們的問題,首先需要建立伺服器套接字,直接運用python的socket模組。

思路是這樣的:

1.首先運用socket模組中的socket類例項化乙個socket物件,設定通訊型別為ipv4,協議家族為tcp(socket類示例化預設引數即為ipv4和tcp);

2.設定socket選項(如果沒有這個選項,當用ctrl+c終止該服務時,需要等上一段時間才能使用同乙個埠號,有的時候確實要等很久);

3.然後使用blind方法,再呼叫listen方法去監聽某個特定的位址

具體的程式如下:

import socket

import os

import time

import math

sk = socket.socket()

#sk.settimeout(1)

sk.setsockopt(socket.sol_socket,socket.so_reuseaddr,1)#當程式終止後,埠釋放

sk.bind(("182.92.108.54",9995))

sk.listen(5)

waittime = 1

#接收等待時間為1s,可以根據自己的要求來設定

while true:

print("wait for connecting... ... ....")

conn,address = sk.accept()

print("connected!")

#獲取檔案大小

datasize = os.stat("rtcnew.bin").st_size

#conn.sendall(str(datasize))

print("data size:%d" % datasize)

sendsizeonce = 1024

sendonce =

#time.sleep(5)

#傳送包的格式為:序號+「;」+資料,便於客戶端知道傳送的是哪個資料段

sendonce = str(0)+";"+str(datasize)

print("send line:0 ")

#先將檔案大小包傳送至客戶端

while true:

try:

print("try send data to client")

conn.sendall(sendonce)

time.sleep(waittime)

recvdata = conn.recv(1024,socket.msg_dontwait)#如果沒有接收到資料,則會觸發錯誤,直接進入except中

print("%s"

%recvdata)

if recvdata == '0':#如果滿足條件才退出

print("recvdatafromclientsuccess:%s,complete data sending"

%recvdata)

break

except:

print("not data received by client,send again... ...")

#將檔案拆分為若干個1024個位元組再傳送

with open("rtcnew.bin","rb") as f:

alldata = f.read()

datalength = 0

numsend = int(math.ceil(datasize/float(sendsizeonce)))

for lineindex in range(numsend):

if lineindex != numsend:

sendonce = str(lineindex+1) + ";"+alldata[lineindex * sendsizeonce:(lineindex+1) * sendsizeonce];

else:

sendonce = str(lineindex+1) + ";"+alldata[lineindex * sendsizeonce:datasize];

datalength += len(sendonce) - len(str(lineindex+1)) - 1

print("send line:%d data length:%d complete: %dpercent"

%(lineindex+1,datalength,datalength * 100/datasize))

#sendonce =

while true:

try:

conn.sendall(sendonce)

time.sleep(waittime)

recvdata = conn.recv(1024,socket.msg_dontwait)

if recvdata == str(lineindex+1):

print("recvdatafromclientsuccess:%s,complete data sending"

%recvdata)

break

except:

print("not data received by client,send again... ...")

思路是這樣的:

1.stm32連線sim800c模組,需要插入乙個能上網的sim卡;

2.通過tcp連線伺服器端;

3.接收到資料,將序號立刻返回至伺服器端;

5.重複3,4步直到所有資料接收完成;

6.從flash特定位址執行flash中的程式。

具體的實現方法可以參考這篇文章以及正點原子的《stm32f1開發指南(精英版)-庫函式版本_v1.0》有關iap的實驗和《an1604b atk-sim800c gsm/gprs 模組使用說明》.

stm32核心**如下:

if(usart3_rx_sta&0x8000)//接收到一次資料       

if(sequence >= 1)

stmflash_write(fwaddr,recvbuf,iindex);

iindex = 0;

}usart3_rx_sta=0;

//將序列返回至伺服器端

sim800c_send_cmd("at+cipsend",">",500); //·¢ëíêý¾ý

u3_printf((char*)(p3+1));

if(sim800c_send_cmd((u8*)0x1a,"send ok",1000)==0);//printf("send!\r\n");

usart3_rx_sta=0;

}usart3_rx_sta=0;

}

python基礎 網路程式設計十(遠端執行命令)

server 下發命令 client 執行命令 ssh協議 import os ret os.popen ls read print ret import subprocess 內建模組 和os模組的功能有相似之處 能執行作業系統的命令的功能 ret subprocess.popen dir 要執行...

網路程式設計雜項 (持續更新)

by fireworks2 foxmail.com 記錄一些小問題,陷阱 1.呼叫bind時,如果位址是0 就是inaddr any那個巨集 就繫結本地所有ip,如果埠是0,就隨機選擇乙個可用的埠 想要知道具體埠,可以呼叫getsockname檢視 2.send recv 與 read write ...

Python網路程式設計 獲取遠端裝置的IP位址

有時需要把裝置的主機名轉換成對應的ip位址,下面是乙個簡單的操作。1 import socket23 4def get remote machine info 定義get remote machine info 函式 5 remote host www.python.org 定義遠端裝置名稱 6tr...