Skip to content

Sanic with websocket

依赖环境

toml
[tool.poetry.dependencies]
python = "^3.9"
sanic = "^23.6.0"

代码

python
from sanic import Sanic, Request, Websocket
from sanic.response import json as resp_json

import json

app = Sanic("app")
SECRET = 'test-test-test'

@app.get("/")
async def index(r: Request):
    return resp_json({"message": "success"}, status=200)


class WsHandle:

    def __init__(self, ws):
        self.ws = ws

    async def recv(self, msg_recv):
        print(f'[recv] {msg_recv}')
        data = json.loads(msg_recv)
        index = data.get('index')
        return index, data
    
    async def close(self):
        await self.ws.close()

    async def send(self, index, data_send):
        data_send_ = {'index': index+1}
        data_send_.update(data_send)
        msg_send = json.dumps(data_send_)
        print(f'[send] {msg_send}')
        await self.ws.send(msg_send)

@app.websocket("/feed")
async def feed(request: Request, ws: Websocket):
    print('new ws connection')
    async for msg_recv in ws:
        h = WsHandle(ws)
        index, data = await h.recv(msg_recv)

        # do something
        message = data.get('message')

        data_send = {'message':message}
        await h.send(index, data_send)

if __name__ == '__main__':
    app.run(host="127.0.0.1", port=80, access_log=True, auto_reload=True)
html
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket Client</title>
</head>

<body>
    <script>

        class MsgHandle {

            constructor(ws) {
                this.ws = ws
            }
            Recv(recv_data) {
                const data = JSON.parse(recv_data);
                let index = data.index;
                return { index, data }
            }
            Send(index, data) {
                this.ws.send(JSON.stringify({ index: index + 1, ...data }));
            }
            sleep(time) {
                return new Promise((resolve) => {
                    setTimeout(resolve, time);
                });
            }
            async SendWait(index, data, wait_time_ms) {
                await this.sleep(wait_time_ms);
                this.Send(index, data)
            }
        }

        const URL_WS = 'ws://127.0.0.1:80/feed';
        const socket = new WebSocket(URL_WS);
        const mh = new MsgHandle(socket);

        socket.addEventListener('open', (event) => {
            console.log('WebSocket连接已打开');
            mh.Send(-1, { message: "init" })
        });

        socket.addEventListener('message', async (event) => {
            let { index, data } = mh.Recv(event.data);
            await mh.SendWait(index, { message: "hello" }, 3000);
        });

        socket.addEventListener('close', (event) => {
            console.log('WebSocket连接已关闭');
        });

        socket.addEventListener('error', (event) => {
            console.error('WebSocket连接错误:', event);
        });

    </script>
</body>

</html>

Released under the MIT License.