WebSocket
一、WebSocket简介
- 顾名思义即:Web + Socket,它是一中TCP协议,当客户端和服务器完成握手,建立连接后,ws 就如普通 socket 一样,在两者之间进行通信。
-
WebSocket 是HTML5的新功能,在HTML5之前,HTML还不支持WebSocket,当时如果要进行实时的内容更新则需要使用到轮询技术。
轮询
客户端一直发请求,服务端一直收请求,直到服务端给客户端响应。
-
优点:响应及时
-
缺点:消耗两端资源,非常严重,占用大量带宽
长轮询
客户端发起请求,服务收到请求,内部进行轮询等待
-
优点:响应及时,节省资源,不会一直发送求情和响应
-
缺点:服务器资源消耗
二、如何使用WebSocket
1. Flask+WebSocket(基础版low)
from flask import Flask,request,render_template from geventwebsocket.websocket import WebSocket # Websocket语法提示 from geventwebsocket.handler import WebSocketHandler # 处理Websocket请求头 from gevent.pywsgi import WSGIServer # 在处理http请求时还能处理websocket请求 app = Flask(__name__) @app.route("/index") def index(): return render_template("ws.html") @app.route("/web") def web(): # 获取用户的socket连接, 并开启语法提示 user_socket = request.environ.get("wsgi.websocket") # type:WebSocket if not user_socket: return "请使用websocket方式连接" while True: # 获取用户发送的信息 user_msg = user_socket.receive() print(user_msg) data = input("回复:").strip() user_socket.send(data) if __name__ == '__main__': # app.run("0.0.0.0", 8000, debug=True) # 当请求进来之后,如果是websocket请求交给WebSocketHandler处理之后再交给APP处理。 http_serv = WSGIServer(("0.0.0.0",8000), app,handler_class=WebSocketHandler) http_serv.serve_forever()
<script type="application/javascript"> var ws = new WebSocket("ws://127.0.0.1:8000/web"); ws.onopen = function () { ws.send("加油") }; ws.onmessage = function (serv_msg) { console.log(serv_msg.data) } </script>
2. Flask+WebSocket(单聊带昵称low)
from flask import Flask, request, render_template from geventwebsocket.websocket import WebSocket from geventwebsocket.websocket import WebSocketError from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer import json app = Flask(__name__) @app.route("/index") def index(): return render_template("ws.html") user_socket_list = [] user_socket_dict = {} @app.route("/ws/<username>") def ws(username): user_socket = request.environ.get("wsgi.websocket") # type:WebSocket if not user_socket: return "请使用WebSocket方式连接" user_socket_dict[username] = user_socket print(user_socket_dict) while True: try: user_msg = user_socket.receive() # 将字符类型的字典,转换为字典类型 user_msg =eval(user_msg) print() for user_name, u_socket in user_socket_dict.items(): if user_name == user_msg["to_user"]: who_send_msg = { "send_user": username, "send_msg": user_msg['send_msg'] } u_socket.send(json.dumps(who_send_msg)) except WebSocketError as e: user_socket_dict.pop(username) print(e) return "断开连接" if __name__ == '__main__': # app.run("0.0.0.0",8000,debug=True) http_serv = WSGIServer(("0.0.0.0", 8000), app, handler_class=WebSocketHandler) http_serv.serve_forever()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> 你是谁:<input type="text" id="username"> 给谁发:<input type="text" id="to_user"> <button id="create_ws" onclick="go_to()">创建ws连接</button> <div style="width: 400px; height: 300px;" id="chat_window"> </div> <div> <input type="text" id="send_msg"> <button id="btn_send">发送消息</button> </div> </body> <script type="application/javascript"> var ws_url = "ws://127.0.0.1:8000/ws/"; var ws = null; // ws.onopen = function () { // ws.send("你好!") // };a function go_to() { var username = document.getElementById("username"); ws = new WebSocket(ws_url + username.value); ws.onmessage = function (serv_msg) { msg = JSON.parse(serv_msg.data); console.log(msg); create_chat("y",msg); }; } function create_chat(self, content) { if (self == "w") { self = "right"; var spantag = document.createElement("span"); spantag.innerText = content.send_msg; var spantag1 = document.createElement("span"); spantag1.innerText = ":我"; } else { self = "left"; var spantag = document.createElement("span"); spantag.innerText = content.send_user + ":"; var spantag1 = document.createElement("span"); spantag1.innerText = content.send_msg; } var divtag = document.createElement("div"); divtag.style = "text-align:" + self; divtag.appendChild(spantag); divtag.appendChild(spantag1); var chat_window = document.getElementById("chat_window"); chat_window.appendChild(divtag); } document.getElementById("btn_send").addEventListener("click", function () { var send_msg = document.getElementById("send_msg"); var to_user = document.getElementById("to_user"); send_msg_json = { send_msg:send_msg.value, to_user :to_user.value }; ws.send(JSON.stringify(send_msg_json)); var s_msg = {send_msg:send_msg.value}; create_chat("w", s_msg); send_msg.value = ""; }) </script> </html>
3.Flask+WebSocket(群聊带昵称low)
from flask import Flask, request, render_template from geventwebsocket.websocket import WebSocket from geventwebsocket.websocket import WebSocketError from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer import json app = Flask(__name__) @app.route("/index") def index(): return render_template("ws.html") user_socket_list = [] user_socket_dict = {} @app.route("/ws/<username>") def ws(username): user_socket = request.environ.get("wsgi.websocket") # type:WebSocket if not user_socket: return "请使用WebSocket方式连接" user_socket_dict[username] = user_socket print(user_socket_dict) while True: try: user_msg = user_socket.receive() for user_name, u_socket in user_socket_dict.items(): who_send_msg = { "send_user": username, "send_msg": user_msg } if user_socket == u_socket: continue u_socket.send(json.dumps(who_send_msg)) except WebSocketError as e: user_socket_dict.pop(username) print(user_socket_dict) print(e) if __name__ == '__main__': # app.run("0.0.0.0",9527,debug=True) http_serv = WSGIServer(("0.0.0.0", 8000), app, handler_class=WebSocketHandler) http_serv.serve_forever()
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> 你是谁:<input type="text" id="username"> <button id="create_ws" onclick="go_to()">创建ws连接</button> <div style="width: 400px; height: 300px;" id="chat_window"> </div> <div> <input type="text" id="send_msg"> <button id="btn_send">发送消息</button> </div> </body> <script type="application/javascript"> var ws_url = "ws://127.0.0.1:8000/ws/"; var ws = null; function go_to() { var username = document.getElementById("username"); ws = new WebSocket(ws_url + username.value); ws.onmessage = function (serv_msg) { msg = JSON.parse(serv_msg.data); create_chat("y",msg); }; } function create_chat(self, content) { if (self == "w") { self = "right"; var spantag = document.createElement("span"); spantag.innerText = content.send_msg; var spantag1 = document.createElement("span"); spantag1.innerText = ":我"; } else { self = "left"; var spantag = document.createElement("span"); spantag.innerText = content.send_user + ":"; var spantag1 = document.createElement("span"); spantag1.innerText = content.send_msg; } var divtag = document.createElement("div"); divtag.style = "text-align:" + self; divtag.appendChild(spantag); divtag.appendChild(spantag1); var chat_window = document.getElementById("chat_window"); chat_window.appendChild(divtag); } document.getElementById("btn_send").addEventListener("click", function () { var send_msg = document.getElementById("send_msg"); ws.send(send_msg.value); var s_msg = {send_msg:send_msg.value}; create_chat("w", s_msg); send_msg.value = ""; }) </script> </html>
三、WebSocket + Flask实现实时更新
实现思路:
- 客户端发起 ws 连接请求。
-
服务器响应,并以key、vlue形式存储用户与用户地址。
-
当某一 ws 向服务器发送信息时,服务器遍历字典中,向里面每一个用户发送信息。
-
ws 断开连接时,从用户字典中剔除用户信息。
创建服务端
即将秃头的程序员