python – 如何在Tornado中创建几个websocket聊天?
我正在尝试使用几个聊天创建一个Tornado应用程序.聊天应该基于
HTML5 websocket. Websockets很好地沟通,但我总是遇到每个消息被发布两次的问题.
该应用程序使用四个类来处理聊天: >聊天包含到目前为止所有已写入的消息以及包含所有应通知的服务员的列表 如何防止多次发布消息? import uuid import tornado.websocket import tornado.web import tornado.template from site import models from site.handler import auth_handler class ChatPool(object): # contains all chats chats = {} @classmethod def get_or_create(cls,scratch_id): if scratch_id in cls.chats: return cls.chats[scratch_id] else: chat = Chat(scratch_id) cls.chats[scratch_id] = chat return chat @classmethod def remove_chat(cls,chat_id): if chat_id not in cls.chats: return del(cls.chats[chat_id]) class Chat(object): def __init__(self,scratch_id): self.scratch_id = scratch_id self.messages = [] self.waiters = [] def add_websocket(self,websocket): self.waiters.append(websocket) def send_updates(self,messages,sending_websocket): print "WAITERS",self.waiters for waiter in self.waiters: waiter.write_message(messages) self.messages.append(messages) class ScratchHandler(auth_handler.BaseHandler): @tornado.web.authenticated def get(self,scratch_id): chat = ChatPool.get_or_create(scratch_id) return self.render('scratch.html',messages=chat.messages,scratch_id=scratch_id) class ScratchWebSocket(tornado.websocket.WebSocketHandler): def allow_draft76(self): # for iOS 5.0 Safari return True def open(self,scratch_id): self.scratch_id = scratch_id scratch = models.Scratch.objects.get(scratch_id=scratch_id) if not scratch: self.set_status(404) return self.scratch_id = scratch.scratch_id self.title = scratch.title self.description = scratch.description self.user = scratch.user self.chat = ChatPool.get_or_create(scratch_id) self.chat.add_websocket(self) def on_close(self): # this is buggy - only remove the websocket from the chat. ChatPool.remove_chat(self.scratch_id) def on_message(self,message): print 'I got a message' parsed = tornado.escape.json_decode(message) chat = { "id": str(uuid.uuid4()),"body": parsed["body"],"from": self.user,} chat["html"] = tornado.escape.to_basestring(self.render_string("chat-message.html",message=chat)) self.chat.send_updates(chat,self) 注意:在@A的反馈之后. Jesse我从Chat更改了send_updates方法.不幸的是,它仍然返回双倍值. class Chat(object): def __init__(self,sending_websocket): for waiter in self.waiters: if waiter == sending_websocket: continue waiter.write_message(messages) self.messages.append(messages) 2.EDIT:我将我的代码与示例提供的演示进行了比较.在websocket示例中,通过WebSocketHandler子类和类方法将新消息传播给服务员.在我的代码中,它是由一个分离的对象完成的: 来自演示: class ChatSocketHandler(tornado.websocket.WebSocketHandler): @classmethod def send_updates(cls,chat): logging.info("sending message to %d waiters",len(cls.waiters)) for waiter in cls.waiters: try: waiter.write_message(chat) except: logging.error("Error sending message",exc_info=True) 我的应用程序使用一个对象而没有WebSocketHandler的子类 class Chat(object): def send_updates(self,sending_websocket): for waiter in self.waiters: if waiter == sending_websocket: continue waiter.write_message(messages) self.messages.append(messages) 解决方法
如果要创建基于Tornado的多聊天应用程序,我建议您使用某种消息队列来分发新消息.这样,您就可以在负载均衡器(如nginx)后面启动多个应用程序进程.否则,您将仅停留在一个进程中,因此在缩放方面受到严重限制.
我更新了我的旧Tornado聊天示例,以支持您要求的多房间聊天.看看存储库: Tornado-Redis-Chat Live Demo 这个简单的Tornado应用程序使用Redis Pub / Sub功能和websockets将聊天消息分发给客户端.通过简单地使用聊天室ID作为发布/订阅频道来扩展多房间功能非常容易. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |