mircopython 环境下socket.recv() 好像会让所有线程被阻塞 这个有办法解决吗?

Viewed 392

设置成非阻塞和0.1秒超时都没有效果,一个线程阻塞所有线程都会阻塞.

import _thread
import os
import socket
import sys
import time
import network

def client():
    while True:
        mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        mysocket.settimeout(0.1)
        ai = socket.getaddrinfo("192.168.137.1", 9989)
        print("Address infos:", ai)
        addr = ai[0][-1]

        try:
                print("Connecting to:", addr)
                mysocket.connect(addr)
        except Exception as e:
            mysocket.close()
            mysocket = None
            print("connect error:", e)
            time.sleep(1)
            continue
        count = 10

        while True:
            try:
                timestamp = int(time.time())
                recvdata = mysocket.recv(1024)
                print(int(time.time())-timestamp)
                print(recvdata)
                time.sleep(0.1)
            except Exception as e:
                print("recv error:", e)
                mysocket.close()
                break

def looptest():
    while True:
        print("loop!")
        time.sleep(1)


if __name__ == '__main__':
    os.exitpoint()
    sta = network.WLAN(network.STA_IF)
    if(sta.active() == False):
        sta.active(True)
    _thread.start_new_thread(looptest, ())
    _thread.start_new_thread(client, ())
    try:
        while True:
            print("main loop")
            time.sleep(0.1)
    except Exception as e:
        sys.print_exception(e)  # 打印异常信息
    finally:
        print("exit")


所有线程会跟着这个3秒一循环,这个怎么解决?

3 Answers

有测试代码吗?新开线程也是阻塞了?

启动后全部变成3s循环

你好,请更新到最新的prerelease固件,有对这个问题进行修复,从这里下载,https://github.com/kendryte/canmv_k230/releases/tag/PreRelease

更新了今天最新的CanMV-K230_LCKFB_micropython_PreRelease_nncase_v2.9.0.img
现在变成了recv会一直阻塞不影响其他线程,但是收不到服务端发来的消息

import _thread
import os
import socket
import struct
import sys
import time
import network

mysocket=None

def client():
    global mysocket
    mysocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#    mysocket.settimeout(0)
#    mysocket.setblocking(False)
    ai = socket.getaddrinfo("192.168.137.1", 9989)
    print("Address infos:", ai)
    addr = ai[0][-1]
    try:
            print("Connecting to:", addr)
            mysocket.connect(addr)
    except Exception as e:
        mysocket.close()
        mysocket = None
        print("connect error:", e)


        # count = 10

def comTcpData(data,cmd):
    count=len(data) + 11
    dsa=bytearray(count)
    header = struct.pack('<H', 0xefef)
    dsa[:2]=header
    dsa[2]=cmd
    dsa[3:7]=int.to_bytes(123456789,4,"little")
    dsa[7:11] = int.to_bytes(len(data), 4, "little")
    dsa[11:]= data
    return dsa


def looptest():
    while True:
        print("loop!")
        time.sleep(1)


def test1():
    while True:
        try:
            print("开始线程")
            timestamp = int(time.time())
            recvdata = mysocket.recv(1024)
            print(int(time.time()) - timestamp)
            print(recvdata)
            time.sleep(0.1)
        except Exception as e:
            print("recv error:", e)
            time.sleep(0.1)
            # mysocket.close()

def heartBt():
    print("开始心跳线程")
    while(True):
        try:
            print("发送心跳!")
            data = comTcpData(b'Heart', 1)
            mysocket.sendall(data)
        except Exception as e:
            print("recv error:", e)
        finally:
            time.sleep(10)

if __name__ == '__main__':
    os.exitpoint()
    sta = network.WLAN(network.STA_IF)
    if(sta.active() == False):
        sta.active(True)
    _thread.start_new_thread(looptest, ())
    client()
#    _thread.start_new_thread(client, ())
    _thread.start_new_thread(test1, ())
    _thread.start_new_thread(heartBt, ())
    try:
        while True:
            print("main loop")
            time.sleep(1)
    except Exception as e:
        sys.print_exception(e)  # 打印异常信息
    finally:
        print("exit")

你好,在test1 函数里添加
global mysocket
mysocket.settimeout(1)
print(f"mysocket {mysocket}")

可以了,感谢

我怎么加了settimeout(1)没效果呢? 板子是创乐博K230,刷了CanMV-K230_micropython_v1.0_sdcard_v1.6_nncase_v2.8.3.img

#配置 tcp/udp socket调试工具
import socket
import network
import time,os


CONTENT = b"""
Hello #%d from k230 canmv MicroPython!
"""
def network_use_wlan(is_wlan=True):
    if is_wlan:
        sta=network.WLAN(0)
        sta.connect("Canaan","Canaan314")
        print(sta.status())
        while sta.ifconfig()[0] == '0.0.0.0':
            os.exitpoint()
        print(sta.ifconfig())
        ip = sta.ifconfig()[0]
        return ip
    else:
        a=network.LAN()
        if not a.active():
            raise RuntimeError("LAN interface is not active.")
        a.ifconfig("dhcp")
        print(a.ifconfig())
        ip = a.ifconfig()[0]
        return ip


def server():
    #获取lan接口
    ip = network_use_wlan(True)

    counter=1

    #建立socket
    global s
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    #设置属性
    s.settimeout(1)
    s.setblocking(False)    
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.settimeout(1)
    s.setblocking(False)    
    #获取地址及端口号 对应地址
    ai = socket.getaddrinfo(ip, 8080)
    print("Address infos:", ai,8080)
    addr = ai[0][-1]
    print("Connect address:", addr)
    #绑定
    s.bind(addr)
    #监听
    s.listen(5)
    print("tcp server %s port:%d\n" % ((ip),8080))


    while True:
        #接受连接
        res = s.accept()
        client_sock = res[0]
        client_addr = res[1]
        print("Client address:", client_addr)
        print("Client socket:", client_sock)
        client_sock.setblocking(False)

        client_stream = client_sock
        #发送字符传
        client_stream.write(CONTENT % counter)

        while True:
            #读取内容
            h = client_stream.read()
            if h == None :
                continue
            if h != b"" :
                print(h)
                #回复内容
                client_stream.write("recv :%s" % h)
            if "end" in h :
                #关闭socket
                client_stream.close()
                break
            os.exitpoint()
            
        counter += 1
        if counter > 10 :
            print("server exit!")
            #关闭
            s.close()
            break
        os.exitpoint()
#main()
server()

加了s.settimeout(1) 3秒响应,不加5秒响应,导致我umodbus跑不通,超时设6秒才能读到寄存器

请更新到最新的prerelease固件,有对这个问题进行修复,从这里下载,https://github.com/kendryte/canmv_k230/releases/tag/PreRelease
从这里下载新固件,3秒响应问题解决了,只剩下umodbus库,只能响应一次都问题了