我想讓 Raspberry Pi 同時從多個帶有 TCP 套接字的 Mbed 微控制器收集資料。現在我有 2 個微控制器定期發送不同的資料包。每當未收到包時,微控制器都會收到一條錯誤訊息,因此在連續 3 次發送失敗后,它將關閉并重新打開其套接字。使用我當前的代碼,我只有 1 個微控制器供電,資料包傳輸成功 100%,但第二個發送資料包可能會短暫作業,但隨后會開始看到丟失的資料包和偶爾的錯誤。
#The server code is
import sys
import socket
from threading import Thread
from socketserver import ThreadingMixIn
# Multithreaded Python server : TCP Server Socket Thread Pool
class ClientThread(Thread):
def __init__(self,ip,port):
Thread.__init__(self)
self.ip = ip
self.port = port
print ("[ ] New server socket thread started for " ip ":" str(port))
def run(self):
while True :
data = conn.recv(64)
#print ("Server received from " ip ".")
if self.ip == '192.168.1.45':
print("hello GPS")
elif self.ip == '192.168.1.253':
time = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3])
vibes = [0]*10
for i in range(0, 10):
vibes[i] = data[(i*2) 4] << 8 | data [(i*2) 5]
print ("Server received from " ip " data: ", time, vibes[0], vibes[1], vibes[2], vibes[3], vibes[4], vibes[5], vibes[6], vibes[7], vibes[8], vibes[9])
# Multithreaded Python server : TCP Server Socket Program Stub
TCP_IP = '0.0.0.0'
TCP_PORT = 80
BUFFER_SIZE = 64 # Usually 1024, but we need quick response
tcpServer = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
tcpServer.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
tcpServer.bind((TCP_IP, TCP_PORT))
threads = []
while True:
tcpServer.listen(4)
print ("Multithreaded Python server : Waiting for connections from TCP clients...")
(conn, (ip,port)) = tcpServer.accept()
newthread = ClientThread(ip,port)
newthread.start()
threads.append(newthread)
我不太明白這段代碼中發生了什么,但我認為它的作業方式是每當建立新連接時,新的 while 回圈開始并且可以與其他回圈同時運行。終端主要隨機列印兩條訊息之一,在微控制器端當其傳感器資料未列印時,我可以看到訊息未收到錯誤。有時我看到一個新執行緒正在啟??動,有時在對資料包進行排序時出現超出范圍的錯誤。
> Server received from 192.168.1.253 data: 236604 12 6 6 25 12 12 37 18
> 18 48 Server received from 192.168.1.253 data: 236423 9 4 4 17 9 9 25
> 14 14 32 [ ] New server socket thread started for 192.168.1.45:58418
> Multithreaded Python server : Waiting for connections from TCP
> clients... Server received from 192.168.1.45 data: 236423 8 6 6 16 12
> 12 23 18 18 30 hello GPS Exception in thread Thread-3: Traceback (most
> recent call last): File "/usr/lib/python3.9/threading.py", line 954,
> in _bootstrap_inner
> self.run() File "/home/pi/Documents/tcp_server2.py", line 25, in run
> vibes[i] = data[(i*2) 4] << 8 | data [(i*2) 5] IndexError: index out of range hello GPS hello GPS [ ] New server socket thread started
> for 192.168.1.253:45001 Multithreaded Python server : Waiting for
> connections from TCP clients...
我可以通過這種方式同時接收多條訊息,還是需要執行諸如同步客戶端以不同時發送之類的操作?將每個客戶端放在一個單獨的埠上并只設定 tcpServer1、tcpServer2、tcpServer3、...更好嗎?
uj5u.com熱心網友回復:
分析:
索引錯誤:索引超出范圍
出現這種情況是因為您的陣列內部沒有足夠的位元組,即len(data)<=(i*2) 4OR len(data)<=(i*2) 5。
解釋:
之后conn.recv(64),不能保證您data會收到一個完整的 64 長位元組陣列。您的論點64只能約束您的資料一次最多接收 64 個位元組,因為根據Python Docs:
socket.recv(bufsize[, 標志])
從套接字接收資料。回傳值是一個位元組物件,表示接收到的資料。一次接收的最大資料量由 bufsize 指定。...
因此,您需要一種方法來確保您的data陣列包含您以后需要的所有位元組。一種替代方法是使用while{...}回圈進行包裝,重復從您的資料接收資料,conn直到它接收到所有 64 個位元組。
解決方案:
可以參考Python官方教程中myreceivce推薦的例程:
# ...
def myreceive(self):
chunks = []
bytes_recd = 0
while bytes_recd < MSGLEN: # in your case, MSGLEN might be 64
chunk = self.sock.recv(min(MSGLEN - bytes_recd, 2048))
if chunk == b'':
# ...
# ...
uj5u.com熱心網友回復:
EveryClientThread使用相同的 global conn,每次接受新連接時都會重新分配,因此所有這些執行緒都嘗試從最近的連接中讀取。您寧愿必須傳遞conn給執行緒并讓它存盤和使用其私有連接,就像您對ip和所做的一樣port。
當您更正此問題時,您還應該列印self.ip而不是ip在run.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/360424.html
