允许浏览器和服务器之间进行 双向通信
server端:
class WebSocketHandler(WebBaseHandler): ''' websocket ''' users = {} # {u'liubei':, # u'rock': } # ------------------提高部分 开始------------------ # 提高部分只是细分发送信息的对象,不是很重要。完成提高部分结束后的 open,on_message, on_close即可。 @classmethod def send_system_message(cls, self, content, send_type): """ :param self: 继承过websocket的base类的实例化对象,主要是self初始化了操作redis,mysql以及user对象的属性 :param content: 储存进redis的list data :param send_type: 发送的类型(发给boss,ceo,员工...),由前端传过来 :return: 系统消息,发送给每个人 """ target = 'system' redis_msg = cls.dict_to_json(self, content, send_type, target) self.conn.rpush('message:%s' % send_type, redis_msg) for f, v in WebSocketHandler.users.items(): v.write_message(redis_msg) @classmethod def dict_to_json(cls, self, content, send_type, target): """ :param self: 继承过websocket的base类的实例化对象,主要是self初始化了操作redis,mysql以及user对象的属性 :param content: 储存进redis的list data :param send_type: 发送的类型(发给boss,ceo,员工...),由前端传过来 :param target: 相当与用来区分缓存key的名字,比如 key_name="cache_list:%s"%target1, ...取对应分类的历史数据 :return: """ msg = { "content": content, "send_type": send_type, "sender": self.current_user.name, "target": target, "datetime": datetime.now().strftime("%Y-%m-%d %H:%M:%S") } return tornado.escape.json_encode(msg) @classmethod def send_role_message(cls, self, content, send_type, roleid): """ :param self: :param content: :param send_type: :param roleid: 通过角色id,反查出属于该角色id的用户 :return: 发送信息给 该角色的所用用户 """ role = Role.by_id(roleid) redis_msg = cls.dict_to_json(self, content, send_type, role.name) self.conn.rpush('message:%s' % send_type, redis_msg) role_users = role.users # [zhangsan, lishi , wangwu] [zhangsan, lishi] for user in role_users: if WebSocketHandler.users.get(user.name, None) is not None: # user.name ['rock':self] WebSocketHandler.users[user.name].write_message(redis_msg) else: # self.conn.lpush("ws:role_off_line",message) pass @classmethod def send_user_message(cls, self, content, send_type, user): """ :param self: :param content: :param send_type: :param user: 发送的对象 :return: 发送信息给改用户 user """ redis_msg = cls.dict_to_json(self, content, send_type, user) self.conn.rpush('message:%s' % send_type, redis_msg) self.conn.rpush('message:%s' % user, redis_msg) # 为了显示未读消息条数 if cls.users.get(user, None) is not None: cls.users[user].write_message(redis_msg) else: # self.conn.lpush("ws:user_off_line",message) pass # ------------------提高部分 结束------------------ def open(self): ''' 有用户进来后,存储该用户 {usernaem: self} self是每个登录用户的实例化类 (用该实例化对象发送是那个消息) ''' WebSocketHandler.users[self.current_user.name] = self pass def on_message(self, message): # 改方法获取消息,前端通过 ws对象.send(msg)发送 # print message # {"content_html":"聊天框输入的内容"} json # {"content_html":"afaf "} msg = tornado.escape.json_decode(message) # 解码 json字符串 --> 字符串 msg.update({ "name": self.current_user.name, "datetime": datetime.now().strftime("%Y-%m-%d %H-%M-%S") }) message = tornado.escape.json_encode(msg) # 转成json self.conn.rpush('message:list', message) # 存储消息为了显示历史消息 # self.write_message(msg) # 就算不转成json,write_message也能自己编码 # WebSocketHandler.users['liubei'].write_message(message) # 这是将不管谁的message只发给用户liubei for f, v in WebSocketHandler.users.items(): v.write_message(message) def on_close(self): pass
前端:和后端一样,都需要完成open,on_message,on_close三个方法
参考中文文档:
posted on 2018-08-20 15:37 阅读( ...) 评论( ...)