websocket
什么是WebSocket? WebSocket是使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动给客户端发送数据,在WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建永久性的链接,并进行双向数据传输. WebSocket的属性 0 表示链接尚未建立 1 表示已经建立链接,可以进行通信 2 表示连接正在关闭 3 表示连接已经关闭或者连接不能打开 WebSocket事件
WebSocket方法
Web框架 轮询: - http - 每秒钟发起至少100次,请求收取信息 - 客户端有一定的处理能力 - 服务器有一定的处理速度 缺点:客户端服务器,资源浪费严重,带宽浪费 长轮询: - http - 先去连接服务器,不断开连接,保持一定的时间,断开瞬间再次发起连接 - 浪费服务器资源严重 - 节省客户端资源 - 相对实时性消息 长连接 - 基于http发起握手 - 保持和服务器的的长连接用不断开,除非有一端主动发起请求 - 在客户端和服务器上各有一个轮询 - 双端分担压力 - 消息及时性 缺点:占用连接资源,占用网络资源 基于WebSocket实现的用例
1 from flask import Flask, render_template, request 2 from geventwebsocket.handler import WebSocketHandler 3 from gevent.pywsgi import WSGIServer 4 from geventwebsocket.websocket import WebSocket 5 6 app = Flask(__name__) 7 # wsgi.websocket = <geventwebsocket.websocket.WebSocket object at 0x0000000003BC8528>, 8 user_scoket_list = [] 9 10 11 @app.route("/conn_ws") 12 def ws_server(): 13 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket 14 user_scoket_list.append(user_socket) 15 16 while 1: 17 msg = user_socket.receive() 18 for i in user_scoket_list: 19 i.send(msg) 20 21 22 @app.route("/") 23 def index(): 24 return render_template("web.html") 25 26 if __name__ == '__main__': 27 28 http_server= WSGIServer(("0.0.0.0",8888),app,handler_class=WebSocketHandler) 29 http_server.serve_forever()
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>群聊</title> 6 </head> 7 <body> 8 <input type="text" id="send_str"> 9 <button id="send_btn" onclick="send()">发送消息</button> 10 <p> 11 12 <div id="char_list"> 13 14 </div> 15 </p> 16 </body> 17 <script type="application/javascript"> 18 19 var ws = new WebSocket("ws://192.168.11.50:8888/conn_ws"); 20 ws.onmessage = function (messageEvent) { 21 22 console.log(messageEvent.data); 23 var ptag = document.createElement("p"); 24 ptag.innerText = messageEvent.data; 25 document.getElementById("char_list").appendChild(ptag); 26 27 28 }; 29 function send() { 30 var send_str = document.getElementById("send_str").value; 31 ws.send(send_str) 32 } 33 34 </script> 35 </html>
WebSocket的工作原理 1.握手 客户端: Sec-WebSocket-Key 响应端: base64(shal(Sec-WebSocket-Key + magic_string)) 2.解密 与127进行"与"为运算,结果是两个数的最小值 1. == 127 第3-10个字节表示该数据的长度 2. == 126 第3-4个字节表示该数据的长度 3. <= 125 当前这个数字就是WebSocket发送的数据长度 WebSocket典型的握手 客户端请求
1 GET / HTTP/1.1 2 Upgrade: websocket 3 Connection: Upgrade 4 Host: example.com 5 Origin: http://example.com 6 Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== 7 Sec-WebSocket-Version: 13
服务端回应
1 HTTP/1.1 101 Switching Protocols 2 Upgrade: websocket 3 Connection: Upgrade 4 Sec-WebSocket-Accept: fFBooB7FAkLlXgRSz0BT3v4hq5s= 5 Sec-WebSocket-Location: ws://example.com/