Websocket

时间:Dec. 20, 2019 分类:

目录:

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")