2016-06-06 32 views
4

我目前正在開發一個服務器程序在Python中使用websockets和asyncio包。websocket.recv()永遠不會返回另一個事件循環內

我得到了一個基本的腳本處理websockets的工作(圖表A)。這個腳本在等待輸入時鎖定,這不是我想要的。

我想象的解決方案是我可以啓動兩個異步任務 - 一個處理輸入和一個處理輸出 - 並在次要事件循環中啓動它們。我必須對協同程序進行一些研究,並且我提出了附件B作爲在事件循環中同時運行兩件事情的概念證明。

現在我所堅持的是圖表C.當我試圖在websockets包的實際場景中使用它時,我發現websocket.recv()永遠不會結束(或者協程永遠不會暫停 - 我我不確定到底發生了什麼)。在展覽A中它工作正常,並且我確定協程肯定至少運行到此時。

任何想法?

附件A:

#!/usr/bin/python3 

import asyncio 
import websockets 
import time 

# This works great! 
async def hello(websocket, path): 
    while True: 
     # This line waits for input from socket 
     name = await websocket.recv() 
     print("< {}".format(name)) 

     # "echo... echo... echo... echo... echo..." 
     greeting = ''.join(name + "... " for x in range(5)) 
     await websocket.send(greeting) 
     print("> {}".format(greeting)) 

     time.sleep(0.1); 

start_server = websockets.serve(hello, '', 26231) 

asyncio.get_event_loop().run_until_complete(start_server) 
asyncio.get_event_loop().run_forever() 

附件B:

#!/usr/bin/python3 
import asyncio 
import time 

class Thing: 
    def __init__(self): 
     pass 
    async def test(self): 
     for x in range(10): 
      print("Hello"+str(x)) 
      await asyncio.sleep(0) 
    def run(self): 
     # Add the task to the event loop twice 
     asyncio.ensure_future(self.test()) 
     asyncio.ensure_future(self.test()) 

t = Thing() 
t.run() 

loop = asyncio.get_event_loop(); 
loop.run_forever() 

附件C:

#!/usr/bin/python3 
import asyncio 
import websockets 
import time 

class WebsocketRequest: 
    def __init__(self, websocket): 
     self.websocket = websocket 

    # Works great 
    async def handle_oputs(self): 
     # This works fine - sends a message 
     # every 10 seconds to the client 
     while True: 
      print("sending...") 
      await self.websocket.send("Hello") 
      print("> {}".format("Hello")) 
      time.sleep(10) 

    # Doesn't work 
    async def handle_iputs(self): 
     # This stops at the await and never receives 
     # any input from the client :/ 
     while True: 
      try: 
       print("receiving...") 
       # This is the line that causes sadness 
       data = await self.websocket.recv() 
       print("< {}".format(data)) 
      except: 
       # This doesn't happen either 
       print("Listener is dead") 

    async def run(self): 

     # This is the part where the coroutine for 
     # a client get split off into two of them 
     # to handle input and output separately. 
     loop = asyncio.new_event_loop() 

     asyncio.set_event_loop(loop) 
     asyncio.ensure_future(self.handle_iputs()) 
     asyncio.ensure_future(self.handle_oputs()) 

     loop.run_forever() 

class WebsocketServer: 
    def __init__(self, address): 
     self.ip = address[0] 
     self.port = address[1] 


    async def hello(self, websocket, path): 
     req = WebsocketRequest(websocket) 
     await req.run() 

    def run(self): 
     loop = asyncio.new_event_loop() 
     asyncio.set_event_loop(loop) 

     start_server = websockets.serve(self.hello, self.ip, self.port) 

     asyncio.get_event_loop().run_until_complete(start_server) 
     asyncio.get_event_loop().run_forever() 
+1

嘗試使用帶有on_message事件的WebSocketApp事件 –

+0

我非常喜歡使用類似的東西 - 事件驅動會更容易處理。我找不到在服務器中使用的WebSocketApp的任何示例;它只是爲了客戶嗎? –

+0

埃裏克,我使用python龍捲風websocket。你可以在這裏找到一個教程http://www.tornadoweb.org/en/stable/websocket.html ...給出了很好的例子。檢查出。是的,on_message將解決這個問題,正如Gabriel已經提到的那樣。 – SanD

回答

-1

也許模塊的WebSocket(不像的WebSockets)可以幫助你。

使用WebsocketApp的很簡單:

from websocket import WebSocketApp  

class ExampleClass(object): 
    def __init__(self): 
     websocket.enableTrace(True) 
     self.ws = websocket.WebSocketApp("ws://echo.websocket.org", 
            on_message=on_message, 
            on_error=on_error, 
            on_close=on_close) 

    def on_message(ws, msg): 
     print "Message Arrived:" + msg 

    def on_error(ws, error): 
     print error 

    def on_close(ws): 
     print "Connection Closed" 

    def on_open(ws): 
     ws.send("Hello!") 

要下載此模塊:https://pypi.python.org/pypi/websocket-client

+0

我找不到任何使用它作爲服務器的例子。據我所知,這隻適用於客戶端通信。 –

0

time.sleep()是阻塞操作,所以任何其他任務不能中斷,並沒有安排。改爲使用await asyncio.sleep()

相關問題