Micropython客户端与Python WebSocket服务器通信异常求助
问题:MicroPython客户端无法向WebSocket服务器发送数据
我尝试用Raspberry Pi Pico W(运行MicroPython)读取温度数据,通过WebSocket发送至Raspberry Pi 4上的Python服务器,服务器仅需打印接收的数据。Python客户端与该服务器通信正常,但MicroPython客户端使用usocket发送时,无报错且返回正确字节数,服务器却未打印数据,寻求解决方法。
原因分析
你的服务器是基于websockets库的WebSocket服务器,而Pico W端用usocket直接发送的是原始TCP数据,两者不兼容:
- WebSocket不是简单的TCP连接,它需要先完成HTTP握手,升级为WebSocket协议,之后的数据也需要按照WebSocket的帧格式传输。
- 直接用
usocket发送字符串,服务器无法识别为合法的WebSocket消息,因此不会触发消息接收逻辑,也不会打印数据。
解决方法
在MicroPython客户端中使用支持WebSocket协议的客户端实现,以下是两种可行方案:
方案1:使用MicroPython WebSocket客户端库
先在Pico W上安装micropython-websocket库(可通过Thonny包管理器安装,或用mpremote上传),再修改客户端代码:
import time import network from websocket import websocket ssid = 'WifiNetwork' password = '12345' wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) # 等待连接 max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('等待连接中...') time.sleep(1) if wlan.status() != 3: raise RuntimeError('网络连接失败') else: print("已连接") status = wlan.ifconfig() print(f'已连接到 {ssid},设备IP: {status[0]}') # 建立WebSocket连接 ws = websocket() ws.connect('ws://10.7.20.162:8000') # 发送消息 msg = 'Hello World from Pico' ws.send(msg) print(f'已发送 {len(msg)} 字节') # 关闭连接 ws.close()
方案2:手动实现WebSocket握手(无需额外库)
如果不想安装第三方库,可以手动完成WebSocket握手并按帧格式发送数据:
import time import network import usocket import ubinascii import uhashlib ssid = 'WifiNetwork' password = '12345' wlan = network.WLAN(network.STA_IF) wlan.active(True) wlan.connect(ssid, password) # 等待连接 max_wait = 10 while max_wait > 0: if wlan.status() < 0 or wlan.status() >= 3: break max_wait -= 1 print('等待连接中...') time.sleep(1) if wlan.status() != 3: raise RuntimeError('网络连接失败') else: print("已连接") status = wlan.ifconfig() print(f'已连接到 {ssid},设备IP: {status[0]}') # 创建TCP套接字 sock = usocket.socket(usocket.AF_INET, usocket.SOCK_STREAM) sockaddr = usocket.getaddrinfo('10.7.20.162', 8000)[0][-1] sock.connect(sockaddr) # 生成WebSocket握手密钥 key = ubinascii.b2a_base64(uhashlib.sha1(str(time.time()).encode()).digest()).strip() # 发送握手请求 handshake = ( f"GET / HTTP/1.1\r\n" f"Host: 10.7.20.162:8000\r\n" f"Upgrade: websocket\r\n" f"Connection: Upgrade\r\n" f"Sec-WebSocket-Key: {key.decode()}\r\n" f"Sec-WebSocket-Version: 13\r\n\r\n" ) sock.send(handshake.encode()) # 接收握手响应(简单校验) resp = sock.recv(1024) if b'101 Switching Protocols' not in resp: raise RuntimeError('WebSocket握手失败') # 封装WebSocket消息帧 def send_ws_message(sock, message): payload = message.encode() # 构建帧:FIN(1) + OPCODE(1:文本) + 掩码(1) + 长度 frame = bytearray() frame.append(0x81) # FIN + TEXT length = len(payload) if length < 126: frame.append(0x80 | length) else: frame.append(0x80 | 126) frame.extend(length.to_bytes(2, 'big')) # 添加掩码(WebSocket客户端必须掩码) mask = ubinascii.unhexlify('12345678')[:4] frame.extend(mask) # 掩码处理 payload for i in range(length): frame.append(payload[i] ^ mask[i % 4]) sock.send(frame) # 发送消息 msg = 'Hello World from Pico' send_ws_message(sock, msg) print(f'已发送 {len(msg)} 字节') time.sleep(0.5) # 等待数据发送完成 sock.close()
验证结果
运行修改后的Pico W客户端,服务器会正常输出:
A client just connected Received message from client: Hello World from Pico A client just disconnected
内容的提问来源于stack exchange,提问作者gb101
相关产品推荐
相关产品推荐

