Websocket
目录:
websocket功能
使用Flask实现Websocket
pip install gevent-websocket
后端代码
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket # 用于语法提示
app = Flask(__name__)
@app.route("/ws")
def ws():
print(request.environ)
return "123"
if __name__ == "__main__":
# 如果是websocket协议添加websocket的请求头
http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
http_serv.serve_forever()
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1:5000/ws")
</script>
</body>
</html>
console可以打印ws对象
ws
WebSocket {url: "ws://127.0.0.1:5000/ws", readyState: 3, bufferedAmount: 0, onopen: null, onerror: null, …}
flask打印
{'HTTP_PRAGMA': 'no-cache', 'wsgi.websocket_version': '13', 'wsgi.websocket': <geventwebsocket.websocket.WebSocket object at 0x000001766CB2B6C8>, 'HTTP_CONNECTION': 'Upgrade', 'HTTP_SEC_WEBSOCKET_EXTENSIONS': 'permessage-deflate; client_max_window_bits', 'wsgi.input': <gevent.pywsgi.Input object at 0x000001766CB45EE8>, 'REMOTE_ADDR': '127.0.0.1', 'HTTP_UPGRADE': 'websocket', 'wsgi.multiprocess': False, 'SERVER_NAME': 'DESKTOP-N06NCHE', 'HTTP_USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36', 'GATEWAY_INTERFACE': 'CGI/1.1', 'HTTP_SEC_WEBSOCKET_KEY': 'zA6Th0X0d5ZPFlgc5YkEFA==', 'wsgi.version': (1, 0), 'SERVER_PROTOCOL': 'HTTP/1.1', 'PATH_INFO': '/ws', 'HTTP_CACHE_CONTROL': 'no-cache', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'HTTP_SEC_WEBSOCKET_VERSION': '13', 'HTTP_ORIGIN': 'http://localhost:63342', 'SERVER_PORT': '5000', 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.multithread': False, 'werkzeug.request': <Request 'http://127.0.0.1:5000/ws' [GET]>, 'HTTP_ACCEPT_ENCODING': 'gzip, deflate, br', 'wsgi.run_once': False, 'HTTP_HOST': '127.0.0.1:5000', 'SERVER_SOFTWARE': 'gevent/1.4 Python/3.5', 'wsgi.input_terminated': True, 'REQUEST_METHOD': 'GET', 'SCRIPT_NAME': '', 'wsgi.url_scheme': 'http', 'QUERY_STRING': '', 'REMOTE_PORT': '7225'
wsgi.websocket就是获取的socket对象
所以获取这个对象进行操作即可
获取数据
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket # 用于语法提示
app = Flask(__name__)
@app.route("/ws")
def ws():
user_socket = request.environ.get("wsgi.websocket") # type: WebSocket
msg = user_socket.receive()
print(msg)
return "123"
if __name__ == "__main__":
# 如果是websocket协议添加websocket的请求头
http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
http_serv.serve_forever()
console直接操作
ws.send("hello")
可以看到后端打印的hello,但是ws的状态readyState变为3了,正在连接应该是3,这里就需要一个while true了
更改为
@app.route("/ws")
def ws():
user_socket = request.environ.get("wsgi.websocket") # type: WebSocket
while 1:
msg = user_socket.receive()
print(msg)
后端发送消息
后端代码
@app.route("/ws")
def ws():
user_socket = request.environ.get("wsgi.websocket") # type: WebSocket
while 1:
msg = user_socket.receive()
print(msg)
user_socket.send(msg)
前端代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1:5000/ws")
ws.onmessage = function(data){
console.log(data)
}
</script>
</body>
</html>
console返回的信息,这是所有websocket信息
MessageEvent {isTrusted: true, data: "123", origin: "ws://127.0.0.1:5000", lastEventId: "", source: null, …}
bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: WebSocket {url: "ws://127.0.0.1:5000/ws", readyState: 1, bufferedAmount: 0, onopen: null, onerror: null, …}
data: "123"
defaultPrevented: false
eventPhase: 0
isTrusted: true
lastEventId: ""
origin: "ws://127.0.0.1:5000"
path: []
ports: []
returnValue: true
source: null
srcElement: WebSocket {url: "ws://127.0.0.1:5000/ws", readyState: 1, bufferedAmount: 0, onopen: null, onerror: null, …}
target: WebSocket {url: "ws://127.0.0.1:5000/ws", readyState: 1, bufferedAmount: 0, onopen: null, onerror: null, …}
timeStamp: 8407.839999999851
type: "message"
userActivation: null
__proto__: MessageEvent
data就是返回的数据,这里返回的数据必须是字符串,json也需要dumps,需要前端再序列化一下Json.parse(data.data)
websocket实现群聊
socket间信息互通
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
from geventwebsocket.websocket import WebSocket # 用于语法提示
app = Flask(__name__)
user_socket_list = []
@app.route("/ws")
def ws():
user_socket = request.environ.get("wsgi.websocket") # type: WebSocket
user_socket_list.append(user_socket)
while 1:
msg = user_socket.receive()
for u_socket in user_socket_list:
u_socket.send(msg)
if __name__ == "__main__":
# 如果是websocket协议添加websocket的请求头
http_serv = WSGIServer(("0.0.0.0", 5000), app, handler_class=WebSocketHandler)
http_serv.serve_forever()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="chat" style="width: 500px; height: 500px;">
</div>
<script type="text/javascript">
var ws = new WebSocket("ws://127.0.0.1:5000/ws")
ws.onmessage = function(data){
var ptag = document.createElement("p");
ptag.innerText = data.data;
document.getElementById("chat").appendChild(ptag)
}
</script>
</body>
</html>
同时打开两个window
前端代码放入templates目录,通过flask直接访问
# -*- coding: utf-8 -*-
from flask import Flask, request, jsonify, 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("/ws")
def ws():
user_socket = request.environ.get("wsgi.websocket") # type: WebSocket
user_socket_list.append(user_socket)
while 1:
msg = user_socket.receive()
for u_socket in user_socket_list:
u_socket.send(msg)
@app.route("/chat")
def chat():
return render_template("w.html")