websocket
阅读目录:
引入
WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。
WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
Web - Socket 客户端 与 服务器 达成一个协议
websocket 客户端 与 websocket 服务器 达成一个websocket协议
上面理解也许不好理解,下面通过代码方式进行深一步理解:
先安装gevent_websocket
基于一个连接的websocket
ws_server.py中:
from flask import Flask,request from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer #应用程序网端接口的一个服务 from geventwebsocket.websocket import WebSocket #做语法提示用 app = Flask(__name__) @app.route("/conn_ws") def ws_app(): # print(request.environ) 这里面有我们需要的 wsgi.websocket ,这是一个websocket连接 use_socket = request.environ.get("wsgi.websocket") #type:WebSocket #告诉编译器 use_socket的语法去WebSocket里面进行查找 #返回值是<geventwebsocket.websocket.WebSocket object at 0x000001FE56EDD868> while True: msg = use_socket.receive() #接收浏览器发来的消息 print(msg) use_socket.send(msg) #将接收到的消息返回给浏览器 # return "666" http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler) #如果不是Http请求,需要用WebSocketHandler处理机制 http_serv.serve_forever() #此时启动没有提示信息,没有日志信息
my_ws.html 文件中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> </body> <script type="application/javascript"> var ws = new WebSocket("ws://127.0.0.1:9527/conn_ws"); #创建一个ws的请求地址 ws.onmessage=function (messageEvent) { #接收服务器send到浏览器端的消息,一旦有消息会触发onmessage 机制,消息为messageEvent,并进行前台打印
console.log(messageEvent.data) }
</script> </html>
需要注意的是:
1.是已经开启的websocket连接
3.开启了websocket连接,然后断开了
最终实现:
浏览器:
服务器端:
websocket群聊
文件代码:
ws.server.py
from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer #应用程序网端接口的一个服务 from geventwebsocket.websocket import WebSocket #做语法提示用 app = Flask(__name__) user_socket_list = [] #存放连接的列表 @app.route("/conn_ws") def ws_app(): use_socket = request.environ.get("wsgi.websocket") #type:WebSocket user_socket_list.append(use_socket) #把每一个到来的连接添加到列表中 while True: msg = use_socket.receive() print(msg) for usocket in user_socket_list: #给每一个连接用户回复消息 usocket.send(msg) @app.route("/") def index(): return render_template("my_ws.html") http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler) http_serv.serve_forever()
my_ws.html 文件中:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p> <div id="chat_list" style="width: 400px ;height: 400px;background: #ede52a;border: solid 1px;"> </div> </p> <input type="text" id="send_str"><button id="send_btn" onclick="send()">发送消息</button> </body> <script type="application/javascript"> var ws = new WebSocket("ws://127.0.0.1:9527/conn_ws"); ws.onmessage=function (messageEvent) { console.log(messageEvent.data); var ptag = document.createElement("p"); ptag.innerText = messageEvent.data; document.getElementById("chat_list").appendChild(ptag); }; function send(){ var send_str = document.getElementById("send_str").value; ws.send(send_str); }; </script> </html>
最终实现:
前端:
服务端:
websocket单聊
ws.server.py
import json from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket app = Flask(__name__) user_socket_dict = {} #创建一个字典数据结构 @app.route("/conn_ws/<user_nick>") #由前端传递一个登陆用户的名称 def ws_app(user_nick): user_socket = request.environ.get("wsgi.websocket") # type:WebSocket user_socket_dict[user_nick] = user_socket #创建一个以登陆用户的姓名为键,连接为值的字典 while True: msg = user_socket.receive() msg_dict = json.loads(msg) #后端接收到前端发送来的字段,需要做反序列化 to_user = msg_dict.get("to_user") #获取接收用户 to_user_socket = user_socket_dict.get(to_user) #获取接收用户的连接 to_user_socket.send(msg) @app.route("/") def index(): return render_template("my_ws.html") if __name__ == '__main__': http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler) http_serv.serve_forever()
my_ws.html 文件中:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p><input type="text" id="nick"> #获取登陆用户的用户名 <button onclick="login()">登陆聊天室</button> </p> 发送给:<input type="text" id="to_user">消息:<input type="text" id="send_str"> <button id="send_btn" onclick="send()">发送消息</button> <p> <div id="chat_list"> </div> </p> </body> <script type="application/javascript"> var ws = null; function login() { var nick = document.getElementById("nick").value; #登陆成功以后创建一个ws连接,并携带登陆用户的名称 ws = new WebSocket("ws://192.168.19.1:9527/conn_ws/" + nick); ws.onmessage = function (messageEvent) { console.log(messageEvent.data); var ptag = document.createElement("p"); var message = JSON.parse(messageEvent.data); #需要将信息转换为对象,字典 ptag.innerText = message.from_user + " : " + message.message; document.getElementById("chat_list").appendChild(ptag); }; } function send() { var message = document.getElementById("send_str").value; var send_str = { from_user: document.getElementById("nick").value, to_user: document.getElementById("to_user").value, message: message }; var json_send_str = JSON.stringify(send_str); ws.send(json_send_str); #发送一个字典类型需要JSON序列化,将发送者,接受者及信息全部发送给后端 } </script> </html>
最终实现:
前端:
websocket单群聊一个py文件
ab_ws_server.py
import json from flask import Flask,request,render_template from geventwebsocket.handler import WebSocketHandler from gevent.pywsgi import WSGIServer from geventwebsocket.websocket import WebSocket app = Flask(__name__) user_socket_dict = {} @app.route("/conn_ws/<user_nick>") def ws_app(user_nick): user_socket = request.environ.get("wsgi.websocket") # type:WebSocket user_socket_dict[user_nick] = user_socket while True: msg = user_socket.receive() msg_dict = json.loads(msg) to_user = msg_dict.get("to_user") if not to_user: # 如果没有接收对象的时候,可以进行群发信息 for usocket in user_socket_dict.values(): print(usocket) usocket.send(msg) to_user_socket = user_socket_dict.get(to_user) to_user_socket.send(msg) @app.route("/") def index(): return render_template("a_my_ws.html") if __name__ == '__main__': http_serv = WSGIServer(("0.0.0.0",9527),app,handler_class=WebSocketHandler) http_serv.serve_forever()
ab_my_ws.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p><input type="text" id="nick"> <button onclick="login()">登陆聊天室</button> </p> 发送给:<input type="text" id="to_user">消息:<input type="text" id="send_str"> <button id="send_btn" onclick="send()">发送消息</button> <p> <div id="chat_list"> </div> </p> </body> <script type="application/javascript"> var ws = null; function login() { var nick = document.getElementById("nick").value; ws = new WebSocket("ws://192.168.11.98:9527/conn_ws/" + nick); ws.onmessage = function (messageEvent) { console.log(messageEvent.data); var ptag = document.createElement("p"); var message = JSON.parse(messageEvent.data); ptag.innerText = message.from_user + " : " + message.message; document.getElementById("chat_list").appendChild(ptag); }; } function send() { var message = document.getElementById("send_str").value; var send_str = { from_user: document.getElementById("nick").value, to_user: document.getElementById("to_user").value, message: message }; var json_send_str = JSON.stringify(send_str); ws.send(json_send_str); } </script> </html>
最终实现: