- A+
所属分类:python
一. WebSocket协议
WebSocket 协议本质上是一个基于 TCP 的协议。
为了建立一个 WebSocket 连接,客户端浏览器首先要向服务器发起一个 HTTP 请求,这个请求和通常的 HTTP 请求不同,包含了一些附加头信息,其中附加头信息”Upgrade: WebSocket”表明这是一个申请协议升级的 HTTP 请求,服务器端解析这些附加的头信息然后产生应答信息返回给客户端,客户端和服务器端的 WebSocket 连接就建立起来了,双方就可以通过这个连接通道自由的传递信息,并且这个连接会持续存在直到客户端或者服务器端的某一方主动的关闭连接。
由于这个规范目前还是处于草案阶段,版本的变化比较快,通常采用 draft-hixie-thewebsocketprotocol-76 版本来描述 WebSocket 协议,详情可访问 http://dev.w3.org/html5/websockets/。
二. Firefox的WebSocket实现
1. 请求
1 2 3 4 5 6 7 8 9 10 11 12 13 |
GET /send HTTP/1.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Encoding: gzip, deflate Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3 Cache-Control: no-cache Connection: keep-alive, Upgrade Host: 127.0.0.1:8200 Origin: http://127.0.0.1:8200 Pragma: no-cache Sec-WebSocket-Key: KOySRTQgzqImO5s57OkTPA== Sec-WebSocket-Version: 13 Upgrade: websocket User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:30.0) Gecko/20100101 Firefox/30.0 |
2. 应答
1 2 3 4 |
HTTP/1.1 101 Switching Protocols Connection: Upgrade Sec-WebSocket-Accept: rr+f1d2NTgfAJeQ8t6/kzHli9ao= Upgrade: websocket |
三. 基于Tornado3.1的WebSocket编程实现
1.HTML示例
注:基于jQuery、Bootstrap,同时将websocket.html保存在websocket.py同级的template目录下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
<html> <head> <link href="http://cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet"> <link href="http://cdn.bootcss.com/bootstrap/3.2.0/css/bootstrap-theme.min.css" rel="stylesheet"> <script src="http://cdn.bootcss.com/jquery/2.1.1/jquery.min.js"></script> <script src="http://cdn.bootcss.com/bootstrap/3.2.0/js/bootstrap.min.js"></script> <script> function send() { var ws = new WebSocket("ws://127.0.0.1:8200/send"); var data = { input:$("#input_data").val(), }; $("#message").empty(); ws.onopen = function() { ws.send(JSON.stringify(data)); }; $("#message").append('<div class="panel-body"><p>'); ws.onmessage = function(event) { $("#message").append(JSON.parse(event.data).input + "<br>"); }; ws.onclose = function(event) { $("#message").append('</p></div>'); }; } </script> </head> <body> <div id="test"> <form class="form-horizontal" role="form"> <div class="panel panel-default"> <div class="panel-heading"> <h5 class="panel-title">>>输入</h5> </div> <div class="panel-body"> <div class="form-group"> <div class="col-md-8"> <input type="text" class="form-control" id="input_data" value=""> </div> </div> <div class="form-group"> <div class="col-md-8"> <button type="submit" class="btn btn-success" id="input_btn" onclick="send();">发送</button> </div> </div> </div> </div> </form> <div class="panel panel-default"> <div class="panel-heading"> <h5 class="panel-title">>> 输出</h5> </div> <div class="panel-body"> <div id="message"></div> </div> </div> </body> </html> |
2.python示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
import os import sys import json import time import tornado.httpserver import tornado.web import tornado.ioloop from tornado import websocket class IndexHandler(tornado.web.RequestHandler): def get(self): self.render("websocket.html") class SendHandler(websocket.WebSocketHandler): clients = set() def open(self): SendHandler.clients.add(self) self.write_message(json.dumps({'input': 'connected...'})) self.stream.set_nodelay(True) def on_message(self, message): message = json.loads(message) self.write_message(json.dumps({'input': 'response...'})) i = 0 while i <= 10: i += 1 self.write_message(json.dumps(message)) time.sleep(1) # 服务器主动关闭 self.close() SendHandler.clients.remove(self) def on_close(self): # 客户端主动关闭 SendHandler.clients.remove(self) if __name__ == '__main__': app = tornado.web.Application( handlers=[ (r"/", IndexHandler), (r"/send", SendHandler) ], debug = False, template_path = os.path.join(os.path.dirname(__file__), "template"), static_path = os.path.join(os.path.dirname(__file__), "static") ) http_server = tornado.httpserver.HTTPServer(app, xheaders=True) http_server.listen(8200) tornado.ioloop.IOLoop.instance().start() |

微信公众号
扫一扫关注运维生存时间公众号,获取最新技术文章~