socketio.emit () при получении пакета UDP - PullRequest
0 голосов
/ 28 декабря 2018

У меня есть сервер флеш-памяти, который обслуживает индекс, который показывает полученные сообщения на веб-страницеСервер получает сообщения через ZMQ или базовый UDP в своих собственных потоках.В тех же потоках он отправляет сообщения на веб-страницу, но принимаются только сообщения потока ZMQ.Скажите, почему не работает вывод UDP-потока?

from flask import Flask, request
from flask_socketio import SocketIO, emit
from threading import Thread
import socket
import time, zmq, pmt

HTTP_PORT = 5000
ZMQ_PORT = 5001
UDP_IP = "127.0.0.1"
UDP_PORT = 5005

app = Flask(__name__, static_url_path="")
# app.config["SECRET_KEY"] = "secret!"
socketio = SocketIO(app)


def background_thread():
    sock = socket.socket(socket.AF_INET,  # Internet
                         socket.SOCK_DGRAM)  # UDP
    sock.bind((UDP_IP, UDP_PORT))

    while True:
        data, addr = sock.recvfrom(1024)  # buffer size is 1024 bytes
        message = 'hello'
        socketio.emit('gnu radio', (message,))
        time.sleep(0.10)
        print "received message:", data


def background_thread_2():
    # Establish ZMQ context and socket
    context = zmq.Context()
    socket = context.socket(zmq.SUB)
    socket.setsockopt(zmq.SUBSCRIBE, "")
    socket.connect("tcp://0.0.0.0:%d" % (ZMQ_PORT))

    while True:
        # Receive decoded ADS-B message from the decoder over ZMQ
        pdu_bin = socket.recv()
        pdu = str(pmt.deserialize_str(pdu_bin)).decode('utf-8', 'ignore').encode("utf-8")
        message = 'hello2'
        socketio.emit('gnu radio', (message,))
        time.sleep(0.10)


@app.route("/")
def index():
    return app.send_static_file("index.html")


@socketio.on("connect")
def connect():
    print("Client connected", request.sid)


@socketio.on("disconnect")
def disconnect():
    print("Client disconnected", request.sid)


if __name__ == "__main__":
    thread = Thread(target=background_thread)
    thread.daemon = True
    thread.start()
    thread = Thread(target=background_thread_2)
    thread.daemon = True
    thread.start()

    socketio.run(app, host="0.0.0.0", port=HTTP_PORT, debug=True)

Получен только Hello2.

1 Ответ

0 голосов
/ 02 января 2019

Проблема на самом деле заключается в перегрузчике Flask.

Когда у вас включен режим отладки, по умолчанию Flask будет использовать перегрузчик - процесс, который отслеживает файлы вашего приложения и перезапускает сервер при их изменении.,По этой причине, когда Flask запускает строку socketio.run и определяет, что режим отладки должен быть включен, он перезапускает скрипт .

Это означает, что фоновые потоки будут запущены снова.Но у вас уже есть работающий поток, связанный с UDP 127.0.0.1:5005.Вторая попытка сделать это не удастся:

Exception in thread Thread-1:
Traceback (most recent call last):
  File "C:\Users\matejcik\AppData\Local\Programs\Python\Python37\lib\threading.py", line 917, in _bootstrap_inner
    self.run()
  File "C:\Users\matejcik\AppData\Local\Programs\Python\Python37\lib\threading.py", line 865, in run
    self._target(*self._args, **self._kwargs)
  File ".\app.py", line 23, in background_thread
    sock.bind((UDP_IP, UDP_PORT))
OSError: [WinError 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted

Старый поток UDP все еще существует, получит сообщения UDP и распечатает их на консоль. Но этот поток до перезапуска все еще ссылается на старую среду Python, поэтому экземпляр socketio устарел, посылая сообщения в void.

Это также причина, почему ZMQ получает сообщения нормально:поскольку подписка ZMQ не является эксклюзивной, можно запустить как старый, так и новый поток, и новый поток сможет без проблем передавать сообщения в новое гнездо.

В общем, взаимодействие потоков и перегрузчикагрязный, см. также https://github.com/miguelgrinberg/Flask-SocketIO/issues/567

Вы можете избежать этой проблемы, указав debug=False или debug=True, use_reloader=False.

...