Python веб-сокет-сервер в потоке? - PullRequest
0 голосов
/ 19 октября 2019

Я пытаюсь запустить сервер веб-сокетов на Raspberry Pi, который отправляет обратно изображение, когда получает какое-либо сообщение (для тестирования), но мне нужно, чтобы это было в отдельном потоке, чем основной поток. И, как вы можете видеть в конце основного раздела, как только я запускаю «сетевой поток», я запускаю бесконечный цикл с печатью только для того, чтобы доказать, что многопоточность работает.

Это код сервера (ятакже прикрепит код клиента)

from autobahn.asyncio.websocket import WebSocketServerProtocol, WebSocketServerFactory
from pathlib import Path
import asyncio
import threading
from threading import Thread
import time

from apscheduler.schedulers.asyncio import AsyncIOScheduler


class MyServerProtocol(WebSocketServerProtocol):

    def onConnect(self, request):
        print ('Thread:', threading.currentThread().getName(), "Client connecting: {0}".format(request.peer))

    def onOpen(self):
        print('Thread:', threading.currentThread().getName(), "WebSocket connection open.")

    def onMessage(self, payload, isBinary):
        if isBinary:
            print( "Binary message received: {0} bytes".format(len(payload)) )
        else:
            print( "Text message received: {0}".format(payload.decode('utf8')) )

        homePath = str(Path.home())

        with open(str(homePath + "/Pictures/rafa.jpg"), "rb") as image:
            f = image.read()
            data = bytearray(f)

        self.sendMessage(bytes(data), True)

    def onClose(self, wasClean, code, reason):
        print('Thread:', threading.currentThread().getName(), "WebSocket connection closed: {0}".format(reason))

def ServerCreate():

    print ('Thread:', threading.currentThread().getName(), 'ServerCreate')


    #loopNetwork = asyncio.get_event_loop()
    loopNetwork = asyncio.new_event_loop()
    asyncio.set_event_loop(loopNetwork)

    factory = WebSocketServerFactory(u"ws://127.0.0.1:9000")
    factory.protocol = MyServerProtocol

    coro = loopNetwork.create_server(factory, '0.0.0.0', 9000)
    server = loopNetwork.run_until_complete(coro)

    try:
        loopNetwork.run_forever()
        print("loop is finished")
    except KeyboardInterrupt:
        print ('Thread:', threading.currentThread().getName(), 'KeyboardInterrupt')
        pass
    finally:
        print ('Thread:', threading.currentThread().getName(), 'Finally - Close')
        server.close()
        loopNetwork.close()


if __name__ == '__main__':

    print ('Main Thread name:', threading.currentThread().getName())
    networkThread = Thread(target=ServerCreate)
    networkThread.isDaemon = True
    networkThread.start()

    #ServerCreate()

    while (True):
        print ('Main Thread name:', threading.currentThread().getName(),'MainTrueLoop')
        time.sleep(4.0)

Это код клиента

from autobahn.asyncio.websocket import WebSocketClientProtocol, WebSocketClientFactory
import io
from PIL import Image
import asyncio
import threading
from threading import Thread


class MyClientProtocol(WebSocketClientProtocol):

    def onConnect(self, response):
        print("Server connected: {0}".format(response.peer))

    def onConnecting(self, transport_details):
        print("Connecting; transport details: {}".format(transport_details))
        return None  # ask for defaults

    def onOpen(self):
        print("WebSocket connection open.")

        def hello():
            self.sendMessage(u"Hello, world!".encode('utf8'))
            self.sendMessage(b"\x00\x01\x03\x04", isBinary=True)
            self.factory.loop.call_later(1, hello)

        # start sending messages every second ..
        hello()

    def onMessage(self, payload, isBinary):
        if isBinary:
            #image = Image.open(io.BytesIO(payload))
            #image.show()
            print("Binary message received: {0} bytes".format(len(payload)))
        else:
            print("Text message received: {0}".format(payload.decode('utf8')))

    def onClose(self, wasClean, code, reason):
        print("WebSocket connection closed: {0}".format(reason))


if __name__ == '__main__':

    print ('Thread:', threading.currentThread().getName(), 'MainFunction!')
    factory = WebSocketClientFactory(u"ws://127.0.0.1:9000")
    factory.protocol = MyClientProtocol

    loop = asyncio.get_event_loop()
    coro = loop.create_connection(factory, '127.0.0.1', 9000)
    #coro = loop.create_connection(factory, '192.168.1.99', 9000)
    loop.run_until_complete(coro)
    loop.run_forever()
    print("loop is finished")
    loop.close()

Это вывод обеих программ при запуске их

Вывод сервера:

Main Thread name: MainThread
Thread: Thread-1 ServerCreate
Main Thread name: MainThread MainTrueLoop
Thread: Thread-1 Client connecting: tcp4:127.0.0.1:51022
Main Thread name: MainThread MainTrueLoop
Thread: Thread-1 WebSocket connection closed: connection was closed uncleanly (peer dropped the TCP connection without previous WebSocket closing handshake)
Main Thread name: MainThread MainTrueLoop
Main Thread name: MainThread MainTrueLoop
Main Thread name: MainThread MainTrueLoop
Main Thread name: MainThread MainTrueLoop
Main Thread name: MainThread MainTrueLoop
Main Thread name: MainThread MainTrueLoop

Вывод клиента

Thread: MainThread MainFunction!
Connecting; transport details: {"peer": "tcp4:127.0.0.1:9000", "is_secure": false, "secure_channel_id": {}}
dropping connection to peer tcp4:127.0.0.1:9000 with abort=True: WebSocket opening handshake timeout (peer did not finish the opening handshake in time)
WebSocket connection closed: connection was closed uncleanly (WebSocket opening handshake timeout (peer did not finish the opening handshake in time))

Как вы можете видеть, что-то сумасшедшее в том, что на выходе сервера мы видим это: Thread:Соединение с клиентом Thread-1: tcp4: 127.0.0.1: 51022

Несмотря на то, что я специально настраиваю порт на 9000, он говорит 51022, но иногда это другое случайное число, обычно около 50000.

Почему это происходит?

...