Http协议是一种请求响应式协议, 不允许服务端主动向客户端发送信息.

短轮询是一种简单的实现服务端推送消息的解决方案, 客户端以一定间隔自动向服务端发送刷新请求, 服务端返回要推送的消息作为响应.

短轮询存在严重缺陷:

  • 短轮询需要进行高频率的网络通信, 且收到大多数轮询请求时服务端没有消息需要推送.

  • 需要维护大量Http连接, 严重消耗资源

如果手写一个短轮询的话你会发现, 短轮询带来的问题不止这些.

长轮询

长轮询是客户端向服务端发送一个刷新请求, 并保持连接打开. 服务端收到请求后不立即响应,等到需要推送消息时再返回. 然后, 客户端再次发送刷新请求并等待推送.

长轮询不再需要频繁发送刷新请求, 但是长期等待的Http连接可能断开, 需要考虑异常处理.

长轮询请求等待过程中服务端处理进程不能被阻塞, tornado的异步IO机制可以方便的使用长轮询.

import tornado.httpserver
from tornado.ioloop import IOLoop
import tornado.options
import json
from tornado.web import Application, RequestHandler, asynchronous class ChatApp(Application):
def __init__(self):
handlers = [
(r'/new-message', NewMsgHandler),
(r'/update-message', UpdateMsgHandler)
]
super(ChatApp, self).__init__(self, handlers=handlers)
self.cache = [] class NewMsgHandler(RequestHandler):
def __init__(self, app):
self.app = app def post(self):
msg = self.get_argument('msg')
self.app.cache.append(msg) class UpdateMsgHandler(RequestHandler):
def __init__(self, app):
self.app = app @asynchronous
def post(self):
if self.request.connection.stream.closed():
return
response_json = json.dumps(self.app.cache)
self.write(response_json)
self.finish() def main():
tornado.options.parse_command_line()
app = ChatApp()
http_server = tornado.httpserver.HTTPServer(app)
http_server.listen(options.port)
tornado.ioloop.IOLoop.instance().start() if __name__ == '__main__':
main()

示例的完整代码,请去草民的仓库

这篇博客提供了一个更为强大的基于长轮询的聊天室, 而且草民非常喜欢他的代码风格.

tornado的长轮询聊天室例子分析

长连接断开的处理机制可以参考这篇文章

WebSocket

WebSocket是HTML5协议中提出的客户-服务器通信协议, 它允许双方以类似TcpSocket的方式进行通信.

它基于标准Http协议实现, 但使用新的ws://URL格式.

Tornado在websocket模块中提供了一个WebSocketHandler类,

  • open方法在一个新的WebSocket连接打开时被调用,

  • on_message方法在连接接收到新的消息时被调用

  • on_close方法在客户端关闭时被调用

  • write_message(message, binary=False)方法可以通过WebSocket向对方发送数据

      - 若binary=False, message可以是string或者dict(会被自动编码为JSON), 
    
      - 若binary=True, message可以是任意byte string

继承WebSocketHandler并重写自己上述方法,实现基于WebSocket的应用.

来自tornado官方文档的示例:

class EchoHandler(WebSocketHandler):

	def allow_draft76(self):
return True def check_origin(self, origin):
return True def open(self):
print "new client opened" def on_close(self):
print "client closed" def on_message(self, message):
self.write_message(message)

allow_draft76check_origin用于进行安全性校验, 只有它们都返回True时WebSocket才能正常连接.

tornado WebSocketHandler文档

Python WebSocket

WebSocket虽然是为Web应用设计的, 为了减轻后端的开发压力可以采用WenSocket代替Tcp Socket与后端交互.

Websocket-client是Python Websocket支持包,可以使用pip安装:

pip install websocket-client

PyPi websocket-client

websocket-client提供了几个低级API:

  • 建立websocket连接

ws = create_connection("ws://echo.websocket.org/")

  • 发送消息

ws.send(msg)

  • 接收消息

result = ws.recv()

  • 关闭连接

ws.close()

websocket也提供了JS风格的API, 来自官方文档的示例:

import websocket
import thread
import time def on_message(ws, message):
print message def on_error(ws, error):
print error def on_close(ws):
print "### closed ###" def on_open(ws):
def run(*args):
for i in range(3):
time.sleep(1)
ws.send("Hello %d" % i)
time.sleep(1)
ws.close()
print "thread terminating..."
thread.start_new_thread(run, ()) if __name__ == "__main__":
websocket.enableTrace(True)
ws = websocket.WebSocketApp(
"ws://echo.websocket.org/",
on_message = on_message,
on_error = on_error,
on_close = on_close
)
ws.on_open = on_open
ws.run_forever()

更多信息请参见Github websocket-client

Tornado长轮询和WebSocket的更多相关文章

  1. tornado 10 长轮询和 websocket

    tornado 10 长轮询和 websocket 一.长轮询 #在网页,我们经常扫码登录,那么问题来了,前端是如何知道用户在手机上扫码登录的呢 这里就需要用到长轮询 #长轮询 #客户端能够不断地向服 ...

  2. 你想了解的轮询、长轮询和websocket都在这里了

    日常生活中,有很多需要数据的实时更新,比如群聊信息的实时更新,还有投票系统的实时刷新等 实现的方式有很多种,比如轮询.长轮询.websocket 轮询 轮询是通过设置页面的刷新频率(设置多长时间自动刷 ...

  3. php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室)

    php websocket-网页实时聊天之PHP实现websocket(ajax长轮询和websocket都可以时间网络聊天室) 一.总结 1.ajax长轮询和websocket都可以时间网络聊天室 ...

  4. 轮询、长轮询和websocket

    一.轮询 在一些需要进行实时查询的场景下应用比如投票系统: 大家一起在一个页面上投票 在不刷新页面的情况下,实时查看投票结果 1.后端代码 from flask import Flask, rende ...

  5. python之轮询、长轮询、websocket

    轮询 ajax轮询 ,ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息. 1.后端代码 from flask import Flask,render_templat ...

  6. 短连接、长连接、轮询、长轮询、WebSocket

    短连接 建立连接——数据传输——关闭连接...建立连接——数据传输——关闭连接 定义:短连接是指通讯双方有数据交互时,就建立一个连接,数据发送完成后,则断开此连接,即每次连接只完成一项业务的发送. 应 ...

  7. tornado长轮询

    1.什么是长轮询顾名思义,长轮询就是不停循环请求服务器,获取最新信息.长轮询分为两类:1)浏览器以固定时间间隔向服务器发送请求缺点是轮询频率要足够快,但又不能太频繁,否则当成百上千个客户端不断请求,会 ...

  8. 长连接、短连接、长轮询和WebSocket

    //转发,格式待整理 2017-08-0519784View0 对这四个概念不太清楚,今天专门搜索了解一下,总结一下: 长连接:在HTTP 1.1,客户端发出请求,服务端接收请求,双方建立连接,在服务 ...

  9. 1.轮询、长轮询、websocket简介

    一.轮询 前端每隔固定时间向后台发送一次请求,询问服务器是否有新数据   缺点: 延迟,需要固定的轮询时间,不一定是实时数据 大量耗费服务器内存和宽带资源,因为不停的请求服务器,很多时候 并没有新的数 ...

随机推荐

  1. openfire消息发送

    找了一些demo,做了一些示例,演示了基于xmpp协议的openfire的客户端之间消息的发送. 代码需要两个包,smack.jar ,smackx.jar. 第一个代码,只是点对点发送消息的,不涉及 ...

  2. DBCC--SHOWCONTIG

    DBCC SHOWCONTIG是显示指定的表的数据和索引的碎片信息. Usage: dbcc SHOWCONTIG [ ( { 'table_name' | table_id | 'view_name ...

  3. 拒绝“高冷”词汇!初学C#中实用的泛型!

    初学C#,整天对着业务逻辑,写反反复复的“过程型”代码逻辑十分枯燥,不如用点新东西提升一下代码效率,让代码看起来更有逼格?! 好,下面我们看看C#中简单易学的泛型. 首先,我写了一个这样的方法 --- ...

  4. ASP.Net Core 2.2 MVC入门到基本使用系列 (四)

    本教程会对基本的.Net Core 进行一个大概的且不会太深入的讲解, 在您看完本系列之后, 能基本甚至熟练的使用.Net Core进行Web开发, 感受到.Net Core的魅力. 本教程知识点大体 ...

  5. 避免图片路径访问405,可以用图片控件来显示局部相对路径,不需要域名就不会出现jpg静态资源访问错误

    <asp:Image ID="Image1" runat="server"/> protected void Page_Load(object se ...

  6. C# npoi 从excel导入datagridviews 批量联网核查

    DataSet ds = new DataSet(); OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Fil ...

  7. webform gridview合并单元格

    gridview合并单元格 由于项目要求,需要合并某些单元格,因此特意封装了如下帮助类: /// <summary> /// 合并单元格 /// </summary> publ ...

  8. js中null, undefined 和 typeof

    参考自:http://www.cnblogs.com/wicub/p/3442891.html typeof 是运算符,注意不是函数,是运算符,其作用,是考察变量究竟是什么类型.或曰,是变量是否定义或 ...

  9. 网易云首席安全架构师谈安全新形势:DDOS两三天,游戏玩家数从几万降到几百

    本文由  网易云发布. 安全是一个永恒的话题,在业务不断云化.攻击越来越复杂的当下,互联网安全呈现了出什么样的严峻形势?对这些形势,网易云又是如何应对的? 网易云首席安全架构师沈明星 4月13日,网易 ...

  10. 手写数字识别---demo

    数据准备 课程中获取数据的方法是从库中直接load_data from keras.datasets import mnist (x_train, y_train), (x_test, y_test) ...