首页 > 解决方案 > udp 端口​​在所有进程中被阻止(python - pi)

问题描述

我在自制安全系统中有一个 Raspberry PI 控制器网络。每一个都为不同的功能启动几个独立的进程,一个 MQTT 代理将所有东西联系在一起。

每个 PI/进程都使用 MQTT 代理的地址进行硬编码,我希望每个 PI/进程都向中央服务器查询代理的位置。

我让每个进程都打开一个用于广播的 UDP 套接字集,并且每个进程都绑定到不同的侦听端口。启动时,它向中央服务器发送一个查询(包括其侦听端口),中央服务器将回复发送到正确的侦听端口。

这仅适用于一个进程,其他进程(在同一个 PI 上)都超时而没有得到响应。Wireshark 显示只有三个中的一个实际上将查询发送到 Wire,奇怪的是打开套接字的最后一个进程是有效的。调试日志中的片段:

mpi@RPI02:~ $ cat /var/log/vlab.debug.log
2020-02-28 17:08:55,242 garagectlr.31: startup
2020-02-28 17:08:55,243 root.2:
2020-02-28 17:08:55,244 root.2: startup
2020-02-28 17:08:55,250 root: looking for broker on port 10417...
2020-02-28 17:08:55,255 garagectlr: looking for broker on port 10416...
2020-02-28 17:08:57,117 sms-receiver.18:
2020-02-28 17:08:57,118 sms-receiver.18: startup
2020-02-28 17:08:57,121 sms-receiver: looking for broker on port 10419...
2020-02-28 17:08:57,124 sms-receiver: rx [mqtt-broker=192.168.99.99]
2020-02-28 17:08:57,225 sms-receiver: located broker at 192.168.99.99
2020-02-28 17:08:57,255 root: FATAL: unable to locate MQTT broker
2020-02-28 17:08:57,260 garagectlr: FATAL: unable to locate MQTT broker
2020-02-28 17:08:57,270  * Running on http://192.168.99.162:6060/ (Press CTRL+C to quit)

这是每个 PI 的相关 python 代码,剪掉了一点:

    #
    # start looking for broker
    #

    # get unique listening port
    listen_port = os.getpid() + 10000
    logging.debug("%s: looking for broker on port %d..."%(self.process,listen_port))
    try:
        sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
        sock.bind(('',listen_port))
    except Exception:
        logging.exception("%s: "%(self.process))

    tries = 0
    try:
        while self.broker == None and tries < 2:
            query = "query mqtt-broker:%s:%d"%(self.process,listen_port)
            sock.sendto(query,("192.168.99.255",1414))
            sock.settimeout(2)
            data,addr = sock.recvfrom(64)
            logging.debug("%s: rx [%s]"%(self.process,data))
            if data[0:5]=='mqtt-':
                self.broker = data[12:]
                time.sleep(.1)
            else:
                time.sleep(1)
                tries = tries + 1
    except Exception:
        print('timeout')
    sock.close()        
    if self.broker == None:
        logging.debug("%s: FATAL: unable to locate MQTT broker"%(self.process))
    else:    
        logging.debug("%s: located broker at %s"%(self.process,self.broker))
        self.sendBoot()            
        self.pubTest("mqtt@%s.%s startup"%(self.process,self.version))            
        m_thread = threading.Thread(target = self.mqtt_thread)
        m_thread.start()

我认为,通过绑定到 RX 的唯一端口,我不会在套接字之间产生任何干扰,但显然只有一个在工作。为什么另外两个甚至不发送查询?

标签: pythonsocketsraspberry-piudp

解决方案


我注意到我在 TRY-CATCH 块中有 WHILE 循环,所以当接收器第一次超时时,while 循环被破坏了。

我将 TRY 放在 WHILE 中,如下所示:

    tries = 0
    query = "query mqtt-broker:%s:%d"%(self.process,listen_port)

    while self.broker == None and tries < 4:
        try:
            sock.sendto(query,("192.168.99.255",1414))
            sock.settimeout(2)
            data,addr = sock.recvfrom(64)
            if data[0:5]=='mqtt-':
                self.broker = data[12:]
                time.sleep(.1)
            else:
                time.sleep(1)
                tries = tries + 1
        except Exception:
            pass    ## timeout

    try:
        sock.close()        
    except Exception:
        logging.exception("%s: "%(self.process))

认为如果查询失败,每个进程都有机会重试。我不确定首先出了什么问题,但是现在这很可靠:

mpi@RPI02:~ $ cat /var/log/vlab.debug.log
2020-02-29 17:07:47,981 root.2:
2020-02-29 17:07:47,982 root.2: startup
2020-02-29 17:07:47,986 garagectlr.31: startup
2020-02-29 17:07:47,992 garagectlr: looking for broker on port 10421...
2020-02-29 17:07:48,010 root: looking for broker on port 10424...
2020-02-29 17:07:49,895 sms-receiver.18:
2020-02-29 17:07:49,896 sms-receiver.18: startup
2020-02-29 17:07:49,901 sms-receiver: looking for broker on port 10423...
2020-02-29 17:07:50,004 sms-receiver: located broker at 192.168.99.99
2020-02-29 17:07:50,048 sms-receiver:  * Running on http://192.168.99.162:6060
2020-02-29 17:07:50,098 garagectlr: located broker at 192.168.99.99
2020-02-29 17:07:50,140 root: located broker at 192.168.99.99
mpi@RPI02:~ $

我认为奇怪的是查询被堆叠,然后以相反的顺序得到满足。但是,嘿,它有效。


推荐阅读