基于Server-Sent Event的简单在线聊天室
一、Web即时通信
所谓Web即时通信,就是说我们可以通过一种机制在网页上立即通知用户一件事情的发生,是不需要用户刷新网页的。Web即时通信的用途有很多,比如实时聊天,即时推送等。如当我们在登陆浏览 知乎时如果有人回答了我们的问题,知乎就会即时提醒我们,再比如现在电子商务的在线客服功能。这些能大大提高用户体验的功能都是基于Web即时通信实现的。
- 普通HTTP流程
- 客户端从服务器端请求网页
- 服务器作出相应的反应
- 服务器返回相应到客户端
而由于HTTP请求是无状态的,也就是说每次请求完成后,HTTP链接就断开了,服务器和浏览器互相之间是完全不可知的,只有下一次再发起一次请求才能更新相应的信息。谈到这里我们就不难想到,我们可以简单的让浏览器每隔一个周期就发起一次请求,这样就能在一定程度上模拟实时效果了,这也就是轮训,术语叫做Polling。
- Polling流程
- 客户端使用普通的http方式向服务器端请求网页
- 客户端执行网页中的JavaScript轮询脚本,定期循环的向服务器发送请求(例如每5秒发送一次请求),获取信息
- 服务器对每次请求作出响应,并返回相应信息,就像正常的http请求一样
通过轮训的方式我们就可以相对即时的获取信息。但是由于轮训的原理是使浏览器频繁的向服务器发起请求,这在一定程度上会造成性能效率问题。为了优化这些性能问题,人们又想到了一种方法。那就是在服务器接收到请求的时候不理解返回,而是只有当有数据变化(或者超时)的时候才返回。这样一来,我们就可以 利用一次请求最大可能的保持连接的有效性,大大的减少了Polling中的请求次数。这个方法叫做长轮训,也叫做Long-Polling。
以上方法是实现Web实时通信的常用方法。当然在HTML5出来之后,我们就有更好的选择啦。在HTML5中,我们可以使用SSE或者是WebSocket。SSE的全称是Server Send Event,听名字就很好理解啦。也就是由服务器来推送数据。看到这里是不是兴奋呢?其实很多情况下,我们只需要这种简单的功能:由服务器推送数据到浏览器。比如推送比赛信息、股价的变化等等。
如果SSE还不能满足我们的需求的话,我们完全就可以使用WebSocket啦。当使用WebSocket时,浏览器和服务器之间就建立了一个全双工通道,互相都可以发送消息,完全的做到了及时,就像使用tcp socket一样。
- SSE和WebSocket的简单对比:
- WebSocket是全双工通道,可以双向通信,功能更强;SSE是单向通道,只能服务器向浏览器端发送。
- WebSocket是一个新的协议,需要服务器端支持;SSE则是部署在HTTP协议之上的,现有服务器软件都支持。
- SSE是一个轻量级协议,相对简单;WebSocket是一种较重的协议,相对复杂。
到这里我们就基本了解了一些事先Web实时通信的机制,下一节中,我们将使用SSE实现一个简单的在线聊天室。
二、基于SSE
的在线聊天室的实现
在线聊天室推送消息有很多种方式,在这门课程中我们使用SSE
来实现。为了方便接收消息,我们借助Redis
的pub/sub
功能来接收和发送消息。Web服务器端我们将使用Flask
实现。如果对Flask不是很熟悉,也可以在实验楼学习相关的Flask课程。(http://www.shiyanlou.com/)
1. SSE
的工作方式
在上面的课程中,我们了解到SSE
是基于HTTP实现的,那么浏览器怎么样知道这是一个服务器事件流呢?其实很简单啦,就是将HTTP的头部Content-Type
设置成text/event-stream
就可以了。其实SSE
,就是浏览器向服务器发送一个HTTP请求,然后服务器不断单向地向浏览器推送"信息",这些信息的格式也非常简单,就是前缀data:
加上发送的数据内容,然后以\n\n
结尾。
2. Redis
中的订阅功能
Redis是很流行的一个内存数据库,可以用于实现缓存,队列等服务。在这门项目课程中我们将使用的Redis
的发布/订阅功 能。简单来说,我们所谓订阅功能就是我们可以订阅一些频道,然后当这些频道有新的消息的时候我们就可以自动接收这些信息。当服务器接收到浏览器POST过来的消息的时候,会将这些信息发布到特定的频道中。接着我们之前订阅了这些频道的客户端就回自动收到这些消息,最后我们就将这些消息通过SSE
推送到客户端。
3. 实现
经过上面的分析,整个聊天室的流程已经很清晰啦。下面通过源代码注释的方式进行分析吧。在/home/shiyanlou
目录下,创建目录code
,然后在该目录下创建源文件app.py
# 消息生成器def event_stream():pubsub = r.pubsub()# 订阅'chat'频道pubsub.subscribe('chat')# 开始监听消息,如果有消息产生在返回消息for message in pubsub.listen():print message# Server-Send Event的数据格式以'data:'开始yield 'data: %s\n\n' % message['data']# 登陆函数,首次访问需要登陆@app.route('/login', methods=['GET', 'POST'])def login():if flask.request.method == 'POST':# 将用户信息记录到session中flask.session['user'] =flask.request.form['user']returnflask.redirect('/')return '<form action="" method="post">user: <inputname="user">'# 接收javascriptpost过来的消息@app.route('/post', methods=['POST'])def post():message = flask.request.form['message']user = flask.session.get('user', 'anonymous')now =datetime.datetime.now().replace(microsecond=0).time()# 将消息发布到'chat'频道中r.publish('chat', u'[%s] %s: %s' % (now.isoformat(), user, message))return flask.Response(status=204)
详细代码请登录实验楼http://www.shiyanlou.com/courses/?course_type=project&tag=all
4. 运行
由于使用了Redis,所以需要安装redis服务器,通过以下步骤就可以将redis服务器,以及相关的依赖包安装好。
$ sudo apt-get update$ sudo apt-get install redis-server$ sudo service redis start$ sudo pip install redis$ sudo pip install flask
安装完成以后,运行,然后通过浏览器访问http://127.0.0.1:8989
就看到效果啦.
另有其他项目课的详细讲解和内容欢迎登陆实验楼http://www.shiyanlou.com/courses/?course_type=project&tag=all
官方网站:实验楼 www.shiyanlou.com
基于Server-Sent Event的简单在线聊天室相关推荐
- 基于 SpringBoot+WebSocket 无DB实现在线聊天室(附源码)
文章目录 基于 SpringBoot+WebSocket 无DB实现在线聊天室 0 项目说明 0.1 样例展示 0.2 源码地址 1 WebSocket 简介 1.1 HTTP 1.2 WebSock ...
- 基于.NET的WebSocket实例:在线聊天室
我相信,有前面两篇的介绍,稍微熟悉socket程序设计的开发人员,应该完全能自行设计出一个基于webSocket的在线交互系统了,趁着我现在还有几分热情,干脆写个完整的聊天室,就当是我为业内socke ...
- 第三章、C#简单界面在线聊天室C#一对多聊天(使用TCP转发实现的在线聊天室,文章末尾附免费项目资源)
C#网络通信系列学习笔记 第一章.C#最简单的控制台网络通信&C#最简单的控制台socket通信 第二章.C#控制台实现一对一聊天&C#socket类的简单封装 第三章.C#简单在线聊 ...
- WebSocket创建局域网在线聊天室
WebSocket的简要介绍: WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议. WebSocket 使得客户端和服务器之间的数据交换变得更加简单,允许服 ...
- java udp简单聊天程序_Java基于UDP协议实现简单的聊天室程序
最近比较闲,一直在抽空回顾一些java方面的技术应用. 今天没什么事做,基于udp协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对java网络编程方面的一个简单回忆. ...
- 嘿从零开始基于SpringBoot 打造在线聊天室(4.4W字最长博文)
文章目录 前言 效果 主页面 消息提示 聊天页面 登录注册 前端 项目构建 依赖 项目结构 登录注册 验证码部分 登录页面 注册页面 主页面 流程 websocket loadmessage 消息发送 ...
- java udp 聊天室_Java基于UDP协议实现简单的聊天室程序
最近比较闲,一直在抽空回顾一些Java方面的技术应用. 今天没什么事做,基于UDP协议,写了一个非常简单的聊天室程序. 现在的工作,很少用到socket,也算是对Java网络编程方面的一个简单回忆. ...
- java源码聊天软件_【原创】基于Java NIO的多人在线聊天工具源码实现(登录,单聊,群聊)...
近来在学习Java NIO网络开发知识,写了一个基于Java NIO的多人在线聊天工具MyChat练练手.源码公开在Coding上: 编写一个基于Java NIO的多人在线聊天工具,需要以下几方面的知 ...
- 从头搭建一个基于 Python 的在线聊天室
本场 Chat,是基于 Python + Redis + Flask 来搭建一个简单易用的在线聊天室.完全从零开始,一步一步完成整个项目. 主要分享内容: Flask 项目结构 Python Redi ...
最新文章
- React 项目--button 绑定事件(15)
- 深度学习在美团配送ETA预估中的探索与实践
- sqlserver2000发布订阅
- cocos2d-x 3.2 listview scorllview 等容器在小米华为等部分手机显示泛白解决
- python框架-Django安装使用
- python typeerror console未定义,Python ctypes加载错误:未定义的符号
- 消息发送到消息接收的整体流程
- [Electron]仿写一个课堂随机点名小项目
- 平面设计师常用的网站|素材路上
- tftp服务器离线安装
- 液晶显示器测试软件6,屏幕坏点检测工具(Datum pixel repair)
- 移动内部疯传的11篇VoLTE学习笔记,看懂了你也是技术大神(二)
- VMware虚拟机多开克隆教程
- LenNet5-MNIST
- 【h.264】 SPS写入timing相关及openh264实现
- PHP有三宝,三、认识三宝
- lsf基础命令bsublmstatbjobs
- Windows下base64编解码命令
- 手写oracle分页,oracle分页代码(超简略写法)
- 参考文献格式(纸质及电子)
热门文章
- 在html中用js代替${pagecontext.request.getcontextpath}这样就不用使用jsp了
- Python Web框架——Flask
- mysql 利用binlog增量备份,还原实例
- seo优化闲了吧----第一回目
- 长脖子鹿省选模拟赛 [LnOI2019SP]快速多项式变换(FPT)
- go学习笔记-标准库
- 使用JDBC操作数据库时,如何提升读取数据的性能?如何提升更新数据的性能?...
- Java 9 揭秘(1. 入门介绍)
- Spark 运行模式 standalong yarn
- PBOC中文件结构,文件类型解析