长轮询

  1.浏览网页时,浏览器会传HTTP 请求到服务器,服务器会根据请求将网页的内容传给浏览器,但是在很多的情况下,使用者会需要看到最新的即时性资讯,例如观看股票市场行情,而在以前只能靠着重新载入网页才能获得最新信息,但是这样不但很浪费时间,也会佔用很多不必要的网络资源,并不是一个好的方式;

  2.长轮询就是解决这个问题的一个办法。

  什么是长轮询

  1.长时间轮询(long-polling)是让服务器在接收到浏览器发出的HTTP 请求后,服务器会等待一段时间,若在这段时间里面伺服器有新的数据更新,它就会把最新的数据传给浏览器,如果等待的时间到了之后也没有新资料的话,就会送一个回应给浏览器,告知浏览器资料没有更新;

  2.长时间轮询可以减少产生轮询(polling)造成网路频宽浪费的状况。

  浏览器如何长轮询

  浏览器向服务器发送Ajax请求,当接收到服务器响应后,需要向服务求发送新的请求。

  服务器如何处理长轮询

  1.服务器端要能够一直保持住客户端的请求,直到有响应消息;同时服务器对请求的处理要支持非阻塞模式;

  2.需要使用Event,python内置Event是阻塞的,gevent的却是非阻塞的。

  设计场景

  1.浏览器请求获取当前的字符信息,并显示;

  2.服务器后天接受某个请求以产生随机字符并存储下来,同时推送给浏览器。

  涉及问题

  1.服务器需知道浏览器获取信息的标识来推送最新的信息;

  2.当浏览器请求更新信息时,服务器可通过Event来保留当前信息,当有新信息来的时候,重设Event来唤醒之前的处理。

  实践

  html代码

<!doctype html>

<html>

<head>

<title>Long Pooling</title>

<style>

#main {

position: absolute;

bottom: 50px;

left: 200px;

}

#state{

float:right;

width:400px;

}

</style>

<head>

<body>

<div id="main">

<div id="inbox"></div>

</div>

<div id="state"></div>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

<script type="text/javascript" charset="utf-8">

var id = null;

function longPolling() {

$.ajax({

url: "update",

data: {"id": id},

type: "POST",

error: function (XMLHttpRequest, textStatus, errorThrown) {

$("#state").append("[state: " + textStatus + ", error: " + errorThrown + " ]<br/>");

},

success: function (result, textStatus) {

console.log(result)

msg_data = eval("(" + result + ")");

$("#inbox").append(msg_data.html);

id = msg_data.id;

console.log(msg_data)

$("#message").val("");

$("#state").append("[state: " + textStatus + " ]<br/>");

},

complete: longPolling

});

}

function sendNewMessage() {

$.ajax({

type: "POST",

url: "new",

});

}

$(function(){

longPolling();

})

</script>

</body>

</html>

test.py

from gevent.pywsgi import WSGIServer

from gevent.event import Event

from cgi import escape

import uuid

import urlparse

import string

import random

def get_request_data(field, env):

try:

request_body_size = int(env.get('CONTENT_LENGTH', 0))

except (ValueError):

request_body_size = 0

request_body = env['wsgi.input'].read(request_body_size)

d = urlparse.parse_qs(request_body)

data = d.get(field, [''])[0]

return data

def generate_response_data(response_body, start_response):

response_headers = [('Content-Type', 'text/html'), ('Content-Length', str(len(response_body)))]

start_response('200 OK', response_headers)

return [response_body]

def generate_json_data(msg_list):

msg_dict = {}

msg_dict["html"] = ""

for msg in msg_list:

msg_dict["html"] += "<div>{0}</div>".format(msg["msg"])

msg_dict["id"] = msg_list[-1]["id"]

res =  str(msg_dict)

return res

def id_generator(size=6, chars=string.ascii_uppercase + string.digits):

return ''.join(random.choice(chars) for _ in range(size))

file = open('longpooling.html')

chat_html = file.read()

class MessgaeBuffer(object):

def __init__(self):

self.cache = []

self.message_event = Event()

def empty(self):

return len(self.cache) == 0

def application(env, start_response):

env_val = env['PATH_INFO']

if env_val == "/create":

msg_item = {}

msg_item["id"] = str(uuid.uuid4())

msg_item["msg"] = id_generator()

print "create msg %s" % str(msg_item)

msgBuffer.cache.append(msg_item)

msgBuffer.message_event.set()

msgBuffer.message_event.clear()

return generate_response_data("", start_response)

elif env_val == "/update":

lastid = escape(get_request_data("id", env))

if msgBuffer.empty() or msgBuffer.cache[-1]["id"] == lastid:

msgBuffer.message_event.wait()

for index,m in enumerate(msgBuffer.cache):

if m["id"] == lastid:

return generate_response_data(generate_json_data(msgBuffer.cache[index+1:])

, start_response)

return generate_response_data(generate_json_data(msgBuffer.cache), start_response)

else:

return generate_response_data(chat_html, start_response)

msgBuffer = MessgaeBuffer()

WSGIServer(('localhost', 8080), application).serve_forever()

原文链接:http://www.maiziedu.com/wiki/frame/polling/

Gevent的长轮询实现方法详解的更多相关文章

  1. 实现Comet(服务器推送)的两种方式:长轮询和http流

    Comet 是一种高级的Ajax技术,实现了服务器向页面实时推送数据的技术,应用场景有体育比赛比分和股票报价等. 实现Comet有两种方式:长轮询与http流 长轮询是短轮询的翻版,短轮询的方式是:页 ...

  2. ajax长轮询 (转)

    javaWeb项目中需要一个实时提醒的功能,也就是某人做了某一操作,可以立即提醒到当前在线的用户 最开始想在用户做了操作后,储存一个状态到数据库中然后用每隔几秒用ajax去请求后台查询数据库来确定是否 ...

  3. Python知识之 方法与函数、偏函数、轮询和长轮询、流量削峰、乐观锁与悲观锁

    方法与函数 函数需要手动传参self.cls,方法自动传,比如对象方法自动传self,类方法自动传cls,而函数相对而言需要手动传,比如静态绑定的函数,self是需要手动传值得,比如我们平常使用的函数 ...

  4. gevent中如何实现长轮询

    浏览网页时,浏览器会传HTTP 请求到服务器,服务器会根据请求将网页的内容传给浏览器,但是在很多的情况下,使用者会需要看到最新的即时性资讯,例如观看股票市场行情,而在以前只能靠着重新载入网页才能获得最 ...

  5. 轮询、长轮询和websocket

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

  6. 轮询、长轮询、websock

    引入 Web端即时通讯技术:即时通讯技术简单的说就是实现这样一种功能:服务器端可以即时地将数据的更新或变化反应到客户端,例如消息即时推送等功能都是通过这种技术实现的.但是在Web中,由于浏览器的限制, ...

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

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

  8. 三周,用长轮询实现Chat并迁移到Azure测试

    公司的OA从零开始进行开发,继简单的单点登陆.角色与权限.消息中间件之后,轮到在线即时通信的模块需要我独立去完成.这三周除了逛网店见爱*看动漫接兼职,基本上都花在这上面了.简单地说就是用MVC4基于长 ...

  9. 用.NET MVC实现长轮询,与jQuery.AJAX即时双向通信

    两周前用长轮询做了一个Chat,并移植到了Azure,还写了篇博客http://www.cnblogs.com/indream/p/3187540.html,让大家帮忙测试. 首先感谢300位注册用户 ...

随机推荐

  1. Application_Error异常处理

    /// <summary> /// 捕捉异常 /// </summary> protected void Application_Error() { // 获得前一个异常的实例 ...

  2. 如何查看tensorflow版本与存储位置

    import tensorflow as tf tf.__version__ __看着是一个下划线,实际上是两个下划线,中间有空格 tf.__path_

  3. VMware 安装CentOS

    使用VMware安装CentOS 6.4 环境:Windows7 , VMware Workstation10, CentOS6.4 为什么选择CentOS ? 主流: 目前的Linux操作系统主要应 ...

  4. grails-shiro权限认证

    一.引用shiro插件 //在BuildConfig的plugins下面添加 compile ":shiro:1.2.1" 二.引用新插件后要进行编译 //grails命令 com ...

  5. log4net使用(winform)

    有时候 会出现错误 :如 log4net 错误 2 未能找到类型或命名空间名称“log4net”(是否缺少 using 指令或程序集引用?) 解决 方法 :http://q.cnblogs.com/q ...

  6. Java程序中调用Python脚本的方法

    在程序开发中,有时候需要Java程序中调用相关Python脚本,以下内容记录了先关步骤和可能出现问题的解决办法. 1.在Eclipse中新建Maven工程: 2.pom.xml文件中添加如下依赖包之后 ...

  7. C语言培训第一天

    下面是一些命令,先来谈谈今天的若干收获吧! 计算机中的一切文件都是以二进制补码的形式存在,问题也就来了. 第一个问题 如果我们给一个无符号的数赋值一个负数,他会读取到什么,又会输出什么?(似乎问题和上 ...

  8. H5网站借鉴

    http://www.rdinfo.com.cn/index.shtml http://www.winployee.com/ http://www.lkkdesign.com/ http://www. ...

  9. 3d中的坐标系的概念

    世界坐标系 世界坐标系是一个特殊的坐标系,它建立了描述其它坐标系所需要的参考框架.从另一方面说能够用世界坐标描述其它坐标系的位置,而不能用更大的.外部的坐标系来描述世界坐标系. 物体坐标系 物体坐标系 ...

  10. Changing Icon File Of Push Button At Runtime In Oracle Forms 6i

    Set Icon_File property in When-Mouse-Enter trigger Suppose you are creating icon based menu system i ...