import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop
import tornado.options
from uuid import uuid4
class ShoppingCart(object):
totalInventory = 10
callbacks = []
carts = {}
def register(self, callback):
self.callbacks.append(callback)
def unregister(self, callback):
self.callbacks.remove(callback)
def moveItemToCart(self, session):
if session in self.carts:
return
self.carts[session] = True
self.notifyCallbacks()
def removeItemFromCart(self, session):
if session not in self.carts:
return
del(self.carts[session])
self.notifyCallbacks()
def notifyCallbacks(self):
for callback in self.callbacks:
callback(self.getInventoryCount())
def getInventoryCount(self):
return self.totalInventory - len(self.carts)
class DetailHandler(tornado.web.RequestHandler):
def get(self):
session = uuid4()
count = self.application.shoppingCart.getInventoryCount()
self.render("index.html", session=session, count=count)
class CartHandler(tornado.web.RequestHandler):
def post(self):
action = self.get_argument('action')
session = self.get_argument('session')
if not session:
self.set_status(400)
return
if action == 'add':
self.application.shoppingCart.moveItemToCart(session)
elif action == 'remove':
self.application.shoppingCart.removeItemFromCart(session)
else:
self.set_status(400)
class StatusHandler(tornado.websocket.WebSocketHandler): def open(self): self.application.shoppingCart.register(self.callback) def on_close(self): self.application.shoppingCart.unregister(self.callback) def on_message(self, message): pass def callback(self, count): self.write_message('{"inventoryCount":"%d"}' % count)
class Application(tornado.web.Application):
def __init__(self):
self.shoppingCart = ShoppingCart()
handlers = [
(r'/', DetailHandler),
(r'/cart', CartHandler),
(r'/cart/status', StatusHandler)
]
settings = {
'template_path': 'templates',
'static_path': 'static'
}
tornado.web.Application.__init__(self, handlers, **settings)
if __name__ == '__main__':
tornado.options.parse_command_line()
app = Application()
server = tornado.httpserver.HTTPServer(app)
server.listen(8000)
tornado.ioloop.IOLoop.instance().start()
Tornado在websocket模块中提供了一个WebSocketHandler类。这个类提供了和已连接的客户端通信的WebSocket事件和方法的钩子。当一个新的WebSocket连接打开时,open方法被调用,而on_message和on_close方法分别在连接接收到新的消息和客户端关闭时被调用。
此外,WebSocketHandler类还提供了write_message方法用于向客户端发送消息,close方法用于关闭连接。
class EchoHandler(tornado.websocket.WebSocketHandler):
def open(self):
self.write_message('connected!')
def on_message(self, message):
self.write_message(message)
正如你在我们的EchoHandler实现中所看到的,open方法只是使用WebSocketHandler基类提供的write_message方法向客户端发送字符串"connected!"。每次处理程序从客户端接收到一个新的消息时调用on_message方法,我们的实现中将客户端提供的消息原样返回给客户端