You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 18:29:50