首页 > 代码库 > 基础入门_Python-模块和包.Gevent异步服务类实现多姿势WEB实时展示?
基础入门_Python-模块和包.Gevent异步服务类实现多姿势WEB实时展示?
内置服务:
1. gevent.server.StreamServer类, 常用于创建异步TCP服务器
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 import time import gevent from gevent.server import StreamServer # 说明: 导入其它模块 def tcp_handler(socket, address): timestamp = time.strftime(‘%Y-%m-%d %H:%M:%S‘, time.localtime()) print ‘%s client(%s) connectd to server.‘ % (timestamp, address) gevent.sleep(5) socket.close() if __name__ == ‘__main__‘: host = ‘‘ port = 80 server = StreamServer((host, port), tcp_handler) server.serve_forever()
2. gevent.server.DatagramServer类, 常用于创建异步UDP服务器
略
扩展服务:
1. gevent.server.pywsgi类, 可用于创建支持单向实时轮询服务器, 轮询(polling),浏览器定期发送Ajax请求,服务器收到请求后立马响应且关闭连接
优点: 后端程序编写比较容易
缺点: 请求中大半无用,浪费带宽和服务器资源
实例: 适用于小型应用
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 import time from gevent.pywsgi import WSGIServer # 说明: 导入其它模块 def ajax_endpoint(environ, start_response): status = ‘200 OK‘ header = [ (‘Content-Type‘, ‘text/html‘), # 允许跨域 (‘Access-Control-Allow-Origin‘, ‘*‘) ] start_response(status, header) return str(time.time()) if __name__ == ‘__main__‘: host = ‘‘ port = 80 server = WSGIServer((host, port), ajax_endpoint) server.serve_forever()
<!DOCTYPE html> <html lang="zh-en"> <head> <meta charset="UTF-8"> <title>polling</title> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> </body> <script type="text/javascript"> setInterval(function () { $.ajax({ url: ‘http://127.0.0.1/‘, success:function (data) { $(‘body‘).append(‘<p>‘ + data + ‘</p>‘) } }) }, 1000) </script> </html>
2. gevent.server.pywsgi类, 可用于创建支持单向实时长轮询服务器, 长轮询(long-polling),客户端向服务器发送Ajax请求,服务器收到请求后hold住连接,直到有消息才返回响应信息并关闭连接,客户端处理完响应信息后再向服务器发送新的请求
优点: 在无消息的情况下不会频繁的请求,耗费资源小
缺点: 服务器hold连接会消耗资源,返回数据顺序无保证,难以管理维护
实例: WebQQ,Hi网页版,Facebook IM等
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 import time import gevent import itertools from gevent.pywsgi import WSGIServer from gevent.queue import Queue, Empty # 说明: 导入其它模块 q = Queue() def generate_data(): cycle = itertools.cycle(xrange(1, 101)) while True: q.put_nowait(str(cycle.next())) gevent.sleep(5) def ajax_endpoint(environ, start_response): status = ‘200 OK‘ header = [ (‘Content-Type‘, ‘text/html‘), # 允许跨域 (‘Access-Control-Allow-Origin‘, ‘*‘) ] start_response(status, header) while True: try: yield q.get(timeout=1) except Empty, e: # 队列为空异常返回 return if __name__ == ‘__main__‘: host = ‘‘ port = 80 g = gevent.spawn(generate_data) g.start() server = WSGIServer((host, port), ajax_endpoint) server.serve_forever() g.join()
<!DOCTYPE html> <html lang="zh-en"> <head> <meta charset="UTF-8"> <title>polling</title> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> </body> <script type="text/javascript"> function longPolling() { $.ajax({ url: ‘http://127.0.0.1/‘, success:function (data) { $(‘body‘).append(‘<p>‘ + data + ‘</p>‘) if(data != ‘100‘) { longPolling() } } }) } longPolling() </script> </html>
说明: 长轮询和轮询的区别在于轮询每次由Ajax发出请求,服务端处理完毕返回响应后就结束了这条连接,而长轮询由Ajax发出请求,但是发出后会阻塞在那里等待回应,服务端只需要从数据源定期取数据就好,超时后会将之前yied的值一次性返回,本次连接断开,所以返回的数据顺序以及数量是不能保证的.
3. gevent.server.pywsgi+geventwebsocket(pip install gevent-websocket)类, 可用于创建支持双向实时WebSockets服务器,但并不是所有的浏览器都支持WebSockets,个人更推荐socket.io,由于它封装了WebSocket,且支持多种连接方式.
#!/usr/bin/env python # -*- coding: utf-8 -*- """ # # Authors: limanman # OsChina: http://xmdevops.blog.51cto.com/ # Purpose: # """ # 说明: 导入公共模块 import time import gevent from gevent.pywsgi import WSGIServer from geventwebsocket import WebSocketError from geventwebsocket.handler import WebSocketHandler # 说明: 导入其它模块 def ws_handler(environ, start_response): ws = environ["wsgi.websocket"] while True: try: ws.send(str(time.time())) gevent.sleep(1) except WebSocketError, e: pass if __name__ == ‘__main__‘: host = ‘‘ port = 5000 server = WSGIServer((host, port), ws_handler, handler_class=WebSocketHandler) server.serve_forever()
<!DOCTYPE html> <html lang="zh-en"> <head> <meta charset="UTF-8"> <title>polling</title> <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js"></script> </head> <body> <div id="conn_status">Not Connected</div> <div id="placeholder" style="width:600px;height:300px;"></div> </body> <script type="text/javascript"> $(function () { var ws = new WebSocket(‘ws://127.0.0.1:5000‘); ws.onmessage = function (event) { $(‘#placeholder ‘).append(‘<p>‘ + event.data + ‘</p>‘) } ws.onopen = function(event) { $(‘#conn_status‘).html(‘<b>Connected</b>‘); } ws.onerror = function(event) { $(‘#conn_status‘).html(‘<b>Error</b>‘); } ws.onclose = function(event) { $(‘#conn_status‘).html(‘<b>Closed</b>‘); } }) </script> </html>
说明: 利用gevent-websocket的WebSocketHandler处理类,在服务端调用send()/receive(),可以很方便的实现Websocket客户端与服务端的实时通信,不妨尝试来一发,运维利器网页版tail -f的Websocket实现?
本文出自 “@Can Up and No BB...” 博客,请务必保留此出处http://xmdevops.blog.51cto.com/11144840/1862737
基础入门_Python-模块和包.Gevent异步服务类实现多姿势WEB实时展示?