tornado+websocket+mongodb实现在线视屏文字聊天
Posted RGC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tornado+websocket+mongodb实现在线视屏文字聊天相关的知识,希望对你有一定的参考价值。
最近学了tornado和mongo,所以结合websocket 实现一个聊天功能,从而加深一下相关知识点的印象
1.websocket概览
webscoket是一种全双工通信模式的协议,客户端连接服务端先通过tcp,http转为webscoket协议后,客户端和服务端都可以主动推送消息给另一端,这也是和http协议(服务端只能被动接收消息,无法主动推送消息给客户端)最大的区别。
2.tornado概览
tornado是一种异步网络库的python web框架,最初在 FriendFeed上开发,通过使用非阻塞网络I/O,tornado可以扫描数以万计打开的链接,让它成为给每个用户一个长链接的理想选择。
Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed. By using non-blocking network I/O, Tornado can scale to tens of thousands of open connections, making it ideal for long polling, WebSockets, and other applications that require a long-lived connection to each user.
3.实现在线聊天功能概览
- 判断对方是否在线,保存离线消息,在线时推送过去,并删除离线消息
- 不保存在线消息
- 单点登录模式的聊天
- 同时和多人点对点聊天
4.后端代码
import redis import tornado.httpserver import tornado.ioloop import tornado.web from motor import motor_tornado from tornado import websocket from tornado.gen import coroutine from conf import Config class WebHandler(websocket.WebSocketHandler): # 在线用户dict all_user = {} def initialize(self, mongo, redis): self.mongo = mongo self.redis = redis @property def db(self): return self.mongo.get_database(\'rgc\') @property def col(self): return self.db.get_collection(\'web\') def check_origin(self, origin): return True # 允许WebSocket的跨域请求 @coroutine def on_message(self, message): #因为没有登录相关功能,每次传输都 用 # 拼接 发送者,消息,接受者 resu = str.split(message, \'#\') name = resu[0] val = resu[1] to = resu[2] # 判断对方是否在线 if \'name:{}\'.format(to) not in list(self.all_user.keys()): self.write_message(\'Out Line\') # 存储消息到db # if not self.redis.hget(\'name_list\', \'{}:{}\'.format(name, to)): # self.redis.hset(\'name_list\', \'{}:{}\'.format(name, to), 1) self.col.insert({\'name\': \'{}:{}\'.format(name, to), \'msg\': val}) else: # 发送最新消息 self.all_user[\'name:{}\'.format(to)].write_message(val) # 检查是不是第一次上线 if \'name:{}\'.format(name) not in list(self.all_user.keys()): # 给自己发送历史消息 his_one = self.col.find({\'name\': \'{}:{}\'.format(to, name)}, {\'msg\': 1, \'_id\': 0}) for it in (yield his_one.to_list(100)): self.write_message(it[\'msg\']) # 删除历史消息 self.col.delete_many({\'name\': \'{}:{}\'.format(to, name)}) # 单点登录聊天 self.all_user.update({\'name:{}\'.format(name): self}) # 发给自己 self.write_message(\'send success\') def open(self): pass def on_close(self): # 当客户端关闭连接时,去除内存中保存的用户,让其离线 key = None for k, v in self.all_user.items(): if v == self: key = k break if key: self.all_user.pop(key) print(\'{} out line\'.format(key)) class htmlHandler(tornado.web.RequestHandler): def get(self): self.render("static/index.html") class StaticHandler(tornado.web.RequestHandler): def get(self, file_url): self.render("static/{}".format(file_url)) def make_app(): settings = {\'cookie_secret\': \'dfdfdfd\', \'xsrf_cookies\': True, \'debug\': True} other_db = {\'mongo\': motor_tornado.MotorClient(**Config.get(\'MONGO_CONF\')), \'redis\': redis.StrictRedis()} return tornado.web.Application([ (r\'/web\', WebHandler, other_db), (r\'/\', HtmlHandler), (r\'/static/(.*)\', StaticHandler) ], **settings) if __name__ == \'__main__\': app = make_app() http_server = tornado.httpserver.HTTPServer(app) ip=\'127.0.0.1\' port = 8000 http_server.bind(8000, ip) http_server.start(1) print(\'server start! http://{}:{}\'.format(ip, port)) tornado.ioloop.IOLoop.current().start()
5.前端技术:
前端主要使用到了 MediaSource,Blob 等技术,发送视频大致思路为:先获取视频文件发送给服务端,然后从服务端发送给另一个客户端,客户端进行视频解析后播放出来。
效果展示:(因为开启浏览器视频功能,必须在https环境或者本地回环地址(127.0.0.1)中才可),所以本次效果展示是在本地进行展示
- 谷歌浏览器(因为我是后端开发,前端代码没有做兼容,并且界面有点丑)开启两个网页,输入 http://127.0.0.1:8000/
- 进入界面后,在name里输入自己的姓名,message中输入 发送给对方的消息,to 里面输入 对方名字,然后点击发送
- lucy发送工tom的信息,在发送信息时,系统检测到tom给她发了离线消息,所以一并返回给lucy。
- 视频发送测试,name和to用的还是之前的:
-
看一下 浏览器控制台 websocket接口的相关内容:
-
可以看到所有的交流都是在一个 websocket连接中,双方可以互发消息
项目代码所在地: https://github.com/Rgcsh/tornado_websocket
以上是关于tornado+websocket+mongodb实现在线视屏文字聊天的主要内容,如果未能解决你的问题,请参考以下文章
Tornado-第三篇-tornado支持websocket协议
websocket[tornado] 的单个实例可以处理不同的请求吗?
如何在 Tornado 中创建多个 websocket 聊天?