当前位置: 首页 > 工具软件 > flask_api > 使用案例 >

python基于flask_sockets实现WebSocket

阎辰钊
2023-12-01

WebSocket是啥?
WebSocket是HTML5引入的新的通信协议,主要由Web客户端和服务器实现,当然它也可以在Web之外实现。 
与HTTP连接不同,WebSocket连接是客户端和服务器之间永久的双向通信通道,其中任何一个都可以启动交换。 一旦建立,连接一直有效,直到其中一方断开连接。

flask实现websocket的两种方式
flask 实现websocket有两种方式实现,一种是flask_sockets方式,该方式是flask对websocket的最原始封装,功能较为单一,第二种方式Flask-SocketIO对websocket的封装,该方式所能提供功能较多,不但实现了socket的基本通信功能,也可以结合flask相关接口,使其更加完备,因此网上对该api介绍也较多。

使用Flask-Sockets
服务端

服务端receive()方法,必须接收客户端发送的数据,才能实现两两互相通信。
 

#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: 415900617@qq.com
@software: PyCharm
@file: flaskWebSocket.py
@time: 2019/2/19 10:20
@describe: flask_sockets 实现websocket
"""
import json
import sys
import os
from flask_sockets import Sockets
import time
from gevent import monkey
from flask import Flask
from gevent import pywsgi
from geventwebsocket.handler import WebSocketHandler
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
monkey.patch_all()
 
app = Flask(__name__)
sockets = Sockets(app)
now = time.strftime('%Y-%m-%d-%H-%M-%S', time.localtime(time.time()))
 
 
@sockets.route('/test')  # 指定路由
def echo_socket(ws):
    while not ws.closed:
        ws.send(str("message test!"))  # 回传给clicent
        """ 服务端必须接收到客户端发的消息才能保持该服务运行,如果ws.receive()没有接收到客户端发送的
         消息,那么它会关闭与客户端建立的链接
         底层解释:Read and return a message from the stream. If `None` is returned, then
        the socket is considered closed/errored.
        所以客户端只建立连接,不与服务端交互通信,则无法实现自由通信状态,之后在客户端代码处会有详细内容。
         """
        message = ws.receive()  # 接收到消息
        if message is not None:
            print("%s receive msg==> " % now, str(json.dumps(message)))
            """ 如果客户端未发送消息给服务端,就调用接收消息方法,则会导致receive()接收消息为空,关闭此次连接 """
            ws.send(str(json.dumps(message)))  # 回传给clicent
        else:
            print(now, "no receive")
 
 
@app.route('/')
def hello():
    return 'Hello World! server start!'
 
 
if __name__ == "__main__":
 
    server = pywsgi.WSGIServer(('0.0.0.0', 5000), app, handler_class=WebSocketHandler)
    print('server start')
    server.serve_forever()

 HTML客户端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.2.0/jquery.js"></script>
</head>
<body>
    <div id="time" style="width: 300px;height: 50px;background-color: #0C0C0C;
    color: white;text-align: center;line-height: 50px;margin-left: 40%;font-size: 20px"></div>
 
    <script>
            var ws = new WebSocket("ws://127.0.0.1:5000/test");  #连接server--test
 
            ws.onmessage = function (event) {
                content = document.createTextNode(event.data); # 接收数据
                $("#time").html(content);
 
            };
 
    </script>
    </body>
</html>

 python客户端

#!/usr/bin/env python
# encoding: utf-8
"""
@version: v1.0
@author: W_H_J
@license: Apache Licence
@contact: 415900617@qq.com
@software: PyCharm
@file: flaskclicent.py
@time: 2019/2/19 10:34
@describe: flask_sockets 客户端
"""
import sys
import os
import datetime
sys.path.append(os.path.abspath(os.path.dirname(__file__) + '/' + '..'))
sys.path.append("..")
from websocket import create_connection
# websocket-client
# 通过socket路由访问
now = datetime.datetime.now()
print(now)
 
 
def send_query_webSocket():
    ws = create_connection("ws://10.10.20.21:9000/test")
    result_1 = ws.recv()  # 接收服务端发送的连接成功消息
    print(result_1)
    """
    上面recv()方法接收服务端 发送的第一条消息:ws.send(str("message test!"))  # 回传给clicent
    下面再要接收消息,必须先给服务端发送一条消息,不然服务端message = ws.receive() 的receive方法
    没有收到消息,而这里直接调用rece()方法去接收服务端消息,则会导致服务端关闭此次连接;
    底层方法介绍:Read and return a message from the stream. If `None` is returned, then
        the socket is considered closed/errored.
    虽然此次连接关闭了,但是对于客户端来说并不知情,而客户端recv()方法又是一个阻塞方式运行,所以会导致
    客户端永远阻塞在这里无法关闭,这也是flask_sockets 客户端服务端交互的一个缺点吧。
    """
    ws.send("I am test msg!")
    result = ws.recv()
    print(result)
    ws.close()
    return True
 
 
if __name__ == '__main__':
    send_query_webSocket()

 

 类似资料: