2016-02-23 76 views
1

我是新來的異步編程。我一直在使用python 3.5 asyncio。我想讓服務器能夠接收來自websocket機器客戶端(GPS)的數據,並且能夠呈現html頁面作爲websocket服務器的瀏覽器客戶端。我已經使用websockets爲我的機器客戶端和端口8765之間的服務器之間的連接。爲了呈現網頁我已經在端口8888(該HTML文件在./views/index.html)使用龍捲風。該代碼只適用於websocket服務器。當我添加龍捲風服務器時,代碼的表現很奇怪,我不知道爲什麼。必須有asyncio用法。如果我之前websocket或龍捲風每次都會關閉。

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

放置

app = make_app() 
app.listen(8888) 
tornado.ioloop.IOLoop.current().start() 

,WebSocket的服務器無法連接。如果我做了相反的事情,龍捲風服務器不會運行。

由於我是異步編程新手,請大家幫助我。 server.py,index.html和client.py(機器客戶端)在下面給出。

server.py

#!/usr/bin/env python 

import tornado.ioloop 
import tornado.web 

import asyncio 
import websockets 

class MainHandler(tornado.web.RequestHandler): 
    def get(self): 
     self.render("./views/index.html", title = "GPS") 

def make_app(): 
    return tornado.web.Application([ 
     (r"/", MainHandler), 
    ]) 

clients = [] 

async def hello(websocket, path): 
    clients.append(websocket) 
    while True: 
     name = await websocket.recv() 
     print("< {}".format(name)) 

     print(clients) 
     greeting = "Hello {}!".format(name) 
     for each in clients: 


      await each.send(greeting) 
      print("> {}".format(greeting)) 

start_server = websockets.serve(hello, 'localhost', 8765) 
print("Listening on *8765") 

app = make_app() 
app.listen(8888) 
print("APP is listening on *8888") 

tornado.ioloop.IOLoop.current().start() 
asyncio.get_event_loop().run_until_complete(start_server) 

asyncio.get_event_loop().run_forever() 

client.py

#!/usr/bin/env python 


import serial 
import time 
import asyncio 
import websockets 

ser =serial.Serial("/dev/tty.usbmodem1421", 9600, timeout=1) 

async def hello(): 
    async with websockets.connect('ws://localhost:8765') as websocket: 
     while True: 
      data = await retrieve() 
      await websocket.send(data) 
      print("> {}".format(data)) 
      greeting = await websocket.recv() 
      print("< {}".format(data)) 


async def retrieve(): 
     data = ser.readline() 
     return data #return the location from your example 

asyncio.get_event_loop().run_until_complete(hello()) 
asyncio.get_event_loop().run_forever() 

./views/index.html

<html> 
    <head> 
     <title>{{ title }}</title> 
    </head> 
    <body> 
     <script> 
      var ws = new WebSocket("ws://localhost:8765/"), 
      messages = document.createElement('ul'); 
      ws.onopen = function(){ 
       ws.send("Hello From Browser") 
      } 
      ws.onmessage = function (event) { 

      var messages = document.getElementsByTagName('ul')[0], 
       message = document.createElement('li'), 
       content = document.createTextNode(event.data); 
      message.appendChild(content); 
      messages.appendChild(message); 
     }; 
     document.body.appendChild(messages); 
    </script> 

回答

2

只能運行一個事件循環一個一段時間(除非你給每一個自己的線程,但是這是非常複雜的)。幸運的是,Tornado和asyncio之間有一個橋樑,讓他們共享相同的IOLoop。

早在你的程序(如app = make_app()任何龍捲風相關的代碼之前),這樣做:

import tornado.platform.asyncio 
tornado.platform.asyncio.AsyncIOMainLoop().install() 

,不叫IOLoop.current().start()。這將重定向所有使用Tornado的組件來使用asyncio事件循環。

+0

非常感謝。有效。期待與更多異步程序一起工作。 :) – tworitdash