Quart框架教程:构建基础WebSocket聊天服务器

Quart框架教程:构建基础WebSocket聊天服务器

quart An async Python micro framework for building web applications. quart 项目地址: https://gitcode.com/gh_mirrors/qu/quart

前言

在现代Web应用中,实时通信功能变得越来越重要。本教程将指导你如何使用Python的Quart框架构建一个基础的WebSocket聊天服务器。Quart是一个兼容ASGI的Python Web框架,它提供了对WebSocket协议的原生支持,非常适合构建实时应用。

环境准备

1. 创建项目结构

我们首先需要创建一个Python项目。推荐使用Poetry作为项目依赖管理工具:

pip install poetry
poetry new --src chat

这个命令会创建一个名为chat的项目,采用src布局(源代码放在src目录下)。所有后续命令都应该在chat目录下执行。

2. 添加项目依赖

聊天服务器只需要Quart作为主要依赖:

poetry add quart

安装完成后,运行以下命令确保依赖正确安装:

poetry install

核心实现

3. 创建Quart应用

src/chat/__init__.py中创建基础的Quart应用:

from quart import Quart

app = Quart(__name__)

def run() -> None:
    app.run()

为了方便启动应用,我们在pyproject.toml中添加一个脚本:

[tool.poetry.scripts]
start = "chat:run"

现在可以通过以下命令启动应用:

poetry run start

4. 设计前端界面

我们需要一个简单的HTML页面作为聊天界面。在src/chat/templates/index.html中创建:

<script type="text/javascript">
  const ws = new WebSocket(`ws://${location.host}/ws`);

  ws.addEventListener('message', function (event) {
    const li = document.createElement("li");
    li.appendChild(document.createTextNode(event.data));
    document.getElementById("messages").appendChild(li);
  });

  function send(event) {
    const message = (new FormData(event.target)).get("message");
    if (message) {
      ws.send(message);
    }
    event.target.reset();
    return false;
  }
</script>

<div style="display: flex; height: 100%; flex-direction: column">
  <ul id="messages" style="flex-grow: 1; list-style-type: none"></ul>
  <form onsubmit="return send(event)">
    <input type="text" name="message" minlength="1" />
    <button type="submit">Send</button>
  </form>
</div>

然后添加路由处理函数:

from quart import render_template

@app.get("/")
async def index():
    return await render_template("index.html")

5. 实现消息代理

为了实现消息的广播功能,我们需要创建一个消息代理。在src/chat/broker.py中:

import asyncio
from typing import AsyncGenerator

class Broker:
    def __init__(self) -> None:
        self.connections = set()

    async def publish(self, message: str) -> None:
        for connection in self.connections:
            await connection.put(message)

    async def subscribe(self) -> AsyncGenerator[str, None]:
        connection = asyncio.Queue()
        self.connections.add(connection)
        try:
            while True:
                yield await connection.get()
        finally:
            self.connections.remove(connection)

这个代理实现了基本的发布-订阅模式,使用Python的asyncio.Queue来管理消息。

6. WebSocket路由实现

现在我们可以实现WebSocket路由了:

import asyncio
from quart import websocket
from chat.broker import Broker

broker = Broker()

async def _receive() -> None:
    while True:
        message = await websocket.receive()
        await broker.publish(message)

@app.websocket("/ws")
async def ws() -> None:
    try:
        task = asyncio.ensure_future(_receive())
        async for message in broker.subscribe():
            await websocket.send(message)
    finally:
        task.cancel()
        await task

这里需要注意:

  • 接收消息的任务需要独立运行,与发送消息并发执行
  • 必须正确处理任务取消和资源清理
  • 当用户断开连接时,会触发CancelledError,确保资源被正确释放

测试与验证

7. 编写测试用例

我们需要验证WebSocket功能是否正常工作:

import asyncio
from quart.testing.connections import TestWebsocketConnection as _TestWebsocketConnection
from chat import app

async def _receive(test_websocket: _TestWebsocketConnection) -> str:
    return await test_websocket.receive()

async def test_websocket() -> None:
    test_client = app.test_client()
    async with test_client.websocket("/ws") as test_websocket:
        task = asyncio.ensure_future(_receive(test_websocket))
        await test_websocket.send("message")
        result = await task
        assert result == "message"

安装测试依赖:

poetry add --dev pytest-asyncio

配置pyproject.toml

[tool.pytest.ini_options]
asyncio_mode = "auto"

运行测试:

poetry run pytest tests/

进阶思考

目前实现的聊天服务器有以下限制:

  1. 消息只在单个服务器实例的内存中共享
  2. 没有用户认证机制
  3. 前端界面非常基础

对于生产环境,你可以考虑:

  • 使用Redis等外部消息代理替代内存实现
  • 添加用户认证和房间功能
  • 改进前端界面和错误处理

总结

通过本教程,我们实现了一个基础的WebSocket聊天服务器,涵盖了:

  • Quart应用的基本结构
  • WebSocket路由的实现
  • 异步消息代理模式
  • 测试WebSocket应用的方法

这为构建更复杂的实时应用打下了良好基础。Quart的ASGI特性使得它非常适合这类实时应用场景。

quart An async Python micro framework for building web applications. quart 项目地址: https://gitcode.com/gh_mirrors/qu/quart

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

班岑航Harris

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值