文章目錄
- ??UDP通信,客戶端與服務器??
- 📢TCP與UDP優缺點
- ??UDPClient —— 客戶端請求
- 1.1 創建STA模式
- 1.2 激活station模式
- 1.3 連接到您的WiFi網路
- 1.4 檢查連接是否建立
- 1.5 創建socket物件
- 1.6 構建ServerIP+ServerPort
- 1.7 發起請求
- 1.8 回應請求
- 1.9 關閉socket
- ?UDPClient 示例
- 本地局域網PC機構建UDPServer,ESP32訪問它
- ??UDPServer —— 服務端回應
- 2.1 創建STA模式
- 2.2 激活station模式
- 2.3 連接到您的WiFi網路
- 2.4 檢查連接是否建立
- 2.5 創建socket物件
- 2.6 構建ServerIP+ServerPort
- 2.7 系結地址
- 2.8 回應請求
- 2.9 關閉socket
- ?UDPServer 示例
- 本地局域網PC機構建UDPClient,訪問ESP32 UDPServer
??博主介紹??
😬 作者:單片機菜鳥哥
👉火爆博客:ESP8266 Arduino教程
零基礎從入門到熟悉Arduino平臺下開發ESP8266,同時會涉及網路編程知識,專欄文章累計超過60篇,分為基礎篇、網路篇、應用篇、高級篇,涵蓋ESP8266大部分開發技巧,
👻最近更新:ESP32 MicroPython應用系列
講解Python在esp32上的應用,包括網路請求、爬蟲
??UDP通信,客戶端與服務器??
前面的博文中,博主講述的內容基本上都是Tcp以及Http通信的內容,那么我們當然得講解一下Tcp的另外一個兄弟——UDP,
📢TCP與UDP優缺點
- TCP是
面向連接,也就是發送資料之前是需要建立連接;UDP是面向無連接的,即發送資料之前不需要建立連接,
- 首先 UDP 是不需要和 TCP一樣在發送資料前進行
三次握手建立連接的,想發資料就可以開始發送了,并且也只是資料報文的搬運工,不會對資料報文進行任何拆分和拼接操作,(也就是每個資料報之間是獨立的,沒有任何關聯先后順序,因此應用層資料必須選擇合適大小的報文資料,)- 在網路資料傳輸模型中,發送端應用層將資料傳遞給傳輸層的 UDP,UDP 協議只會給資料增加一個 UDP 頭標識下是 UDP 協議,然后就傳遞給網路IP層了
在接收端,網路IP層將資料傳遞給傳輸層,UDP 只去除 IP 報文頭就傳遞給應用層,不會任何拼接操作
- TCP提供
可靠的服務,也就是說,通過TCP連接傳送的資料,無差錯,不丟失,不重復,且按序到達;UDP盡最大努力做到可靠,即不保證絕對可靠,
- 首先不可靠性體現在
無連接上,通信都不需要建立連接,想發就發,這樣的情況肯定不可靠,
并且收到什么資料就傳遞什么資料,并且也不會備份資料,發送資料也不會關心對方是否已經正確接收到資料了,- UDP 沒有
擁塞控制,一直會以恒定的速度發送資料,即使網路條件不好,也不會對發送速率進行調整,這樣實作的弊端就是在網路條件不好的情況下可能會導致丟包,但是優點也很明顯,在某些實時性要求高的場景(比如電話會議)就需要使用 UDP 而不是 TCP,因為丟棄了一些資料無關緊要,
- UDP具有較好的實時性,作業
效率比TCP高,適用于對高速傳輸和實時性有較高的通信或廣播通信,
- UDP頭部開銷小,傳輸資料報文時是很高效的
-
每一條TCP連接只能是
點到點的;UDP支持一對一,一對多,多對一和多對多的互動通信, -
TCP對系統資源要求較多,UDP對系統資源要求較少,
UDP 是 User Datagram Protocol 的簡稱,是一種無連接、不可靠的協議,每一個資料報都是一個獨立的資訊,它在網路上以任何可能的路徑傳到目的地,但不保證是否真的傳到目的地、是否程序中真的保證了資料的完整性!
UDP就好像無手機時代,你要去探望親戚,但是你不知道親戚有沒有在家(也就是說可能會丟包);
TCP就好像有手機時代,你要去探望親戚,你會打電話過去提前溝通好,你會確保親戚在家里才會買東西過去探望(資料不會丟包);
建議看這篇之前,可以先看看 ESP32 MicroPython開發之旅 網路篇④ ——TCP通信 核心思想需要理解,
在ESP32 MicroPython中,進行TCP/UDP通訊主要用到了usocket(套接字)模塊,
- MicroPython 提供豐富的
網路功能,可以加快物聯網應用的開發速度,了解網路功能之后,就可以將產品輕松的接入網路,實作更多物聯網功能,- 在使用 MicroPython 進行網路編程首先需要了解的就是 usocket 模塊,模塊提供對
BSD套接字介面的訪問,
而在TCP/UDP基礎上我們又會TCPClient、TCPServer、UDPClient、UDPServer,TCP相關已經講解,本篇重點講解UDP相關,
目前基于UDP的應用層協議應用比較廣泛就是
CoAP,
而在usocket 模塊中,我們需要了解一些基本的常量(網路基礎)含義:
- IP地址型別
socket.AF_INET =2 — TCP/IP –
IPv4
socket.AF_INET6 =10 — TCP/IP –IPv6
- 套接字型別
socket.
SOCK_STREAM=1 — TCP流(重點)
socket.SOCK_DGRAM=2 — UDP資料報(重點)
socket.SOCK_RAW =3 — 原始套接字
socket.SO_REUSEADDR =4 — socket可重用
- IP協議號(在大多數情況下不需要指定這個,MicroPython也不推薦,作為了解即可)
socket.IPPROTO_TCP =16
socket.IPPROTO_UDP =17
- 原因:因為 SOCK_STREAM 套接字型別會自動選擇 IPPROTO_TCP 和 SOCK_DGRAM - IPPROTO_UDP, 因此,這些常量的唯一實際用途是作為 setsockopt() 的引數,
??UDPClient —— 客戶端請求

這里博主特意用兩種顏色區分STA和Client程序,
1.1 創建STA模式
import network
sta_if = network.WLAN(network.STA_IF)
注意:
- 第一次按照MicroPython韌體的時候,ESP32配置為熱點模式,因此AP_IF介面有效,STA_IF介面無效,
1.2 激活station模式
import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
1.3 連接到您的WiFi網路
import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect('<your ESSID>', '<your password>')
1.4 檢查連接是否建立
import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.isconnected()
1.5 創建socket物件
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
- 使用給定的地址群、型別和協議號創建一個新的socket物件
1.6 構建ServerIP+ServerPort
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
- 將引數翻譯為一個5
元組序列,該序列包含創建一個與設備連接的socket所需的全部必要引數, - 該5元組串列有以下結構:
(family, sockettype, proto, canonname,
sockaddr)
簡稱ftpca
family: 表示socket使用的協議簇,常用的協議簇包括AF_UNIX(本機通信)/AF_INET(TCP/IP協議簇中的IPv4協議)/AF_INET6(TCP/IP協議簇中的IPv4協議),在python的socket包中,用1表示AF_UNIX,2表示AF_INET,10表示AF_INET6,sockettype:表示socket的型別,常見的socket型別包括SOCK_STREAM(TCP流)/SOCK_DGRAM(UDP資料報)/SOCK_RAW(原始套接字),其中,SOCK_STREAM=1,SOCK_DGRAM=2,SOCK_RAW=3proto:顧名思義,就是指定協議,套介面所用的協議,如呼叫者不想指定,可用0,常用的協議有,IPPROTO_TCP(=6)和IPPTOTO_UDP(=17),它們分別對應TCP傳輸協議、UDP傳輸協議,canonname:主機名字sockaddr:IP地址+埠
注意:
- socket.getaddrinfo 回傳的是一個元組陣列(這里可以解釋
[0][-1]的由來,獲取到IP地址和埠元組),類似于:
[(2, 1, 6, '', ('220.181.111.86', 80)),
(2, 2, 17, '', ('220.181.111.86', 80)),
(2, 1, 6, '', ('123.125.114.144', 80)),
(2, 2, 17, '', ('123.125.114.144', 80)),
(2, 1, 6, '', ('220.181.111.85', 80)),
(2, 2, 17, '', ('220.181.111.85', 80))]
- 這個ftpca的 前三位可以用來構造一個socket,
2 是 AF_INET
1 是 SOCK_STREAM
6 是 IPPROTOTCP
1.7 發起請求
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 發起請求
print("esp32 micropython udp")
s.sendto("esp32 micropython udp",addr)
1.8 回應請求
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 發起請求
print("esp32 micropython udp")
s.sendto("esp32 micropython udp",addr)
# 回應請求
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
- 從socket上接收資料,回傳值是一個表示接收到的資料的位元組物件,要接收到的資料最大數量由緩沖區大小指定,
1.9 關閉socket
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 發起請求
print("esp32 micropython udp")
s.sendto("esp32 micropython udp",addr)
# 回應請求
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
# 關閉socket
s.close()
- 標記關閉的socket,一旦發生這種情況,所有將對socket物件進行的操作都將失敗,遠程端將無法再接收到任何資料(佇列資料重繪后),
- Socket在垃圾回收時自動關閉,但是建議您明確地關閉它們
?UDPClient 示例
本地局域網PC機構建UDPServer,ESP32訪問它
步驟:
- 網路除錯助手打開
UDPServer,獲取本地主機IP地址和本地主機埠號port- esp32創建
UDPClient,連接該IP和port,發送 “esp32 micropython udp”過去
- 新建
network_udp_client.py
# 匯入usocket模塊
import usocket
# 匯入網路模塊
import network
# 定義一個連接函式
def do_connect():
# 創建STA模式
sta_if = network.WLAN(network.STA_IF)
# 回傳網路作業狀態
print('network status1:', sta_if.status())
# 檢查連接是否建立
if not sta_if.isconnected():
print('connecting to network...')
# 激活station模式
sta_if.active(True)
# 連接到您的WiFi網路
sta_if.connect('TP-LINK_5344', 'xxxxxx')
# 回傳網路作業狀態
print('network status2:', sta_if.status())
# 檢查連接是否建立
while not sta_if.isconnected():
pass
# 回傳網路作業狀態
print('network status3:', sta_if.status())
# 開機自動連接
do_connect()
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort,這里得填寫自己的網路除錯助手
addr = usocket.getaddrinfo('192.168.1.105', 32666)[0][-1]
print(addr)
# 發起請求
print("esp32 micropython udp")
s.sendto("esp32 micropython udp",addr)
# 回應請求
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
# 關閉socket
s.close()
- 結果:

>>> %Run -c $EDITOR_CONTENT
network status1: 1010
network status3: 1010
('192.168.1.105', 32666)
esp32 micropython udp
??UDPServer —— 服務端回應

這里博主特意用兩種顏色區分STA和Server程序,
2.1 創建STA模式
import network
sta_if = network.WLAN(network.STA_IF)
注意:
- 第一次按照MicroPython韌體的時候,ESP32配置為熱點模式,因此AP_IF介面有效,STA_IF介面無效,
2.2 激活station模式
import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
2.3 連接到您的WiFi網路
import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.connect('<your ESSID>', '<your password>')
2.4 檢查連接是否建立
import network
sta_if = network.WLAN(network.STA_IF)
sta_if.active(True)
sta_if.isconnected()
2.5 創建socket物件
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
- 使用給定的地址群、型別和協議號創建一個新的socket物件
2.6 構建ServerIP+ServerPort
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
- 將引數翻譯為一個5
元組序列,該序列包含創建一個與設備連接的socket所需的全部必要引數, - 該5元組串列有以下結構:
(family, sockettype, proto, canonname,
sockaddr)
簡稱ftpca
family: 表示socket使用的協議簇,常用的協議簇包括AF_UNIX(本機通信)/AF_INET(TCP/IP協議簇中的IPv4協議)/AF_INET6(TCP/IP協議簇中的IPv4協議),在python的socket包中,用1表示AF_UNIX,2表示AF_INET,10表示AF_INET6,sockettype:表示socket的型別,常見的socket型別包括SOCK_STREAM(TCP流)/SOCK_DGRAM(UDP資料報)/SOCK_RAW(原始套接字),其中,SOCK_STREAM=1,SOCK_DGRAM=2,SOCK_RAW=3proto:顧名思義,就是指定協議,套介面所用的協議,如呼叫者不想指定,可用0,常用的協議有,IPPROTO_TCP(=6)和IPPTOTO_UDP(=17),它們分別對應TCP傳輸協議、UDP傳輸協議,canonname:主機名字sockaddr:IP地址+埠
注意:
- socket.getaddrinfo 回傳的是一個元組陣列(這里可以解釋
[0][-1]的由來,獲取到IP地址和埠元組),類似于:
[(2, 1, 6, '', ('220.181.111.86', 80)),
(2, 2, 17, '', ('220.181.111.86', 80)),
(2, 1, 6, '', ('123.125.114.144', 80)),
(2, 2, 17, '', ('123.125.114.144', 80)),
(2, 1, 6, '', ('220.181.111.85', 80)),
(2, 2, 17, '', ('220.181.111.85', 80))]
- 這個ftpca的 前三位可以用來構造一個socket,
2 是 AF_INET
1 是 SOCK_STREAM
6 是 IPPROTOTCP
2.7 系結地址
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 系結地址
s.bind(addr)
- 將套接字系結到地址,套接字不能是已經系結的,
2.8 回應請求
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 系結地址
s.bind(addr
# 回應請求
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
- 從socket上接收資料,回傳值是一個表示接收到的資料的位元組物件,要接收到的資料最大數量由緩沖區大小指定,
2.9 關閉socket
# 匯入usocket模塊
import usocket
# 創建 udp socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort
addr = socket.getaddrinfo('www.micropython.org', 80)[0][-1]
# 發起請求
print("esp32 micropython udp")
s.sendto("esp32 micropython udp",addr)
# 回應請求
while True:
data = s.recv(100)
if data:
print(str(data, 'utf8'), end='')
else:
break
# 關閉socket
s.close()
- 標記關閉的socket,一旦發生這種情況,所有將對socket物件進行的操作都將失敗,遠程端將無法再接收到任何資料(佇列資料重繪后),
- Socket在垃圾回收時自動關閉,但是建議您明確地關閉它們
?UDPServer 示例
本地局域網PC機構建UDPClient,訪問ESP32 UDPServer
步驟:
- 網路除錯助手打開
UDPClient,獲取本地主機IP地址和本地主機埠號port- esp32創建
UDPServer,處理發過來的資料
- 新建
network_udp_server.py
# 匯入usocket模塊
import usocket
# 匯入網路模塊
import network
# 定義一個連接函式
def do_connect():
# 創建STA模式
sta_if = network.WLAN(network.STA_IF)
# 回傳網路作業狀態
print('network status1:', sta_if.status())
# 檢查連接是否建立
if not sta_if.isconnected():
print('connecting to network...')
# 激活station模式
sta_if.active(True)
# 連接到您的WiFi網路
sta_if.connect('TP-LINK_5344', 'xxxxxxxx')
# 回傳網路作業狀態
print('network status2:', sta_if.status())
# 檢查連接是否建立
while not sta_if.isconnected():
pass
# 回傳網路作業狀態
print('network :', sta_if.ifconfig())
# 開機自動連接
do_connect()
# 創建 UDP socket
s = usocket.socket(usocket.AF_INET,usocket.SOCK_DGRAM)
# 構建ServerIP+ServerPort,這里得填寫自己的網路除錯助手
addr = usocket.getaddrinfo('192.168.1.102', 32666)[0][-1]
print(addr)
# 系結地址
s.bind(addr)
# 回應請求
while True:
data,clientaddr = s.recvfrom(1024)
print("data:",data)
print("from:",clientaddr)
if data:
print(str(data, 'utf8'), end='')
else:
break
# 關閉socket
s.close()
結果:

>>> %Run -c $EDITOR_CONTENT
network status1: 1010
network : ('192.168.1.102', '255.255.255.0', '192.168.1.1', '192.168.1.1')
('192.168.1.102', 32666)
data: b'from Packet Sender'
from: ('192.168.1.105', 64657)
from Packet Senderdata: b'from Packet Sender'
from: ('192.168.1.105', 64657)
from Packet Sender
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/395338.html
標籤:其他
上一篇:redis一萬字精華總結

