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

树莓派Pico搭建RC飞机Web服务器时,如何实现任务与请求监听并行?

问题:树莓派Pico遥控飞机Web服务器阻塞其他任务运行

我用树莓派Pico制作了一架遥控飞机,为实现遥控功能搭建了带控制界面的小型Web服务器,功能正常,但发现飞机指示灯停止闪烁——只有刷新页面或点击按钮时才会闪。原因是微控制器一直在等待Web请求,无法执行其他任务。以下是当前循环代码,plane_duties()包含所有其他任务(比如指示灯闪烁):

while True:
    plane_duties(.05)
    try:
        cl, addr = s.accept()
        request = cl.recv(1024)
        request = str(request)
        tlan_toggle = request.find('tlan=toggle')
        blan_toggle = request.find('blan=toggle')

        if tlan_toggle == 8:
            tlan = not tlan
        if blan_toggle == 8:
            blan = not blan
        print(tlan, blan)
        tlanState = 'Landing is OFF' if tlan else 'Landing is ON'
        tlanStateClass = 'off' if tlan else 'on'
        blanState = 'Cargo is OFF' if blan else 'Cargo is ON'
        blanStateClass = 'off' if blan else 'on'

        response = html.replace('{{tlanStateClass}}', tlanStateClass).replace('{{blanStateClass}}', blanStateClass) % (
            tlanState, blanState)
        cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
        cl.send(response)
        cl.close()

    except OSError as e:
        cl.close()
        print('connection closed')

请问有没有办法在等待Web请求的同时运行其他代码?


解决方法:设置非阻塞套接字+轮询

核心问题是s.accept()是阻塞式调用——程序会卡在这一行直到有Web请求进来,完全无法执行plane_duties()。解决思路是把套接字设为非阻塞模式,这样s.accept()不会一直等待,无请求时直接抛出异常,程序就能继续循环执行plane_duties()。

修改步骤:

  1. 在创建套接字后,添加一行设置非阻塞:
s.setblocking(False)
  1. 修改主循环逻辑,让plane_duties()持续执行,同时处理Web请求:

修改后的完整循环代码:

# 先把套接字设为非阻塞(放在创建s的代码后面)
s.setblocking(False)

while True:
    plane_duties(.05)  # 持续执行飞机的核心任务
    try:
        cl, addr = s.accept()
        # 处理请求的代码保持不变
        request = cl.recv(1024)
        request = str(request)
        tlan_toggle = request.find('tlan=toggle')
        blan_toggle = request.find('blan=toggle')

        if tlan_toggle == 8:
            tlan = not tlan
        if blan_toggle == 8:
            blan = not blan
        print(tlan, blan)
        tlanState = 'Landing is OFF' if tlan else 'Landing is ON'
        tlanStateClass = 'off' if tlan else 'on'
        blanState = 'Cargo is OFF' if blan else 'Cargo is ON'
        blanStateClass = 'off' if blan else 'on'

        response = html.replace('{{tlanStateClass}}', tlanStateClass).replace('{{blanStateClass}}', blanStateClass) % (
            tlanState, blanState)
        cl.send('HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n')
        cl.send(response)
        cl.close()

    except OSError as e:
        # 非阻塞模式下,没请求时会抛出EAGAIN/EWOULDBLOCK异常,直接忽略即可
        if e.args[0] != 11 and e.args[0] != 110:  # 11是Linux下的EAGAIN,110是超时(视Pico系统调整)
            if 'cl' in locals():
                cl.close()
            print('connection closed')

原理说明:

  • 非阻塞模式下,s.accept()不会卡住,没有请求时立刻抛出特定OSError,程序跳过请求处理逻辑,直接回到循环开头执行plane_duties()。
  • 这样plane_duties()能被高频调用,指示灯闪烁这类任务就能正常运行,同时Web请求来了也能及时处理。

如果需要更复杂的多任务管理,也可以考虑用MicroPython的_thread模块创建线程,把Web服务器放在单独线程里执行,但非阻塞套接字的方案更轻量,适合Pico这类资源有限的微控制器。


内容的提问来源于stack exchange,提问作者benji bon

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 15:27:33