You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

76 lines
2.2 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from fastapi import FastAPI, WebSocket, WebSocketDisconnect
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from fastapi.requests import Request
import uvicorn
app = FastAPI()
# 挂载模板目录
templates = Jinja2Templates(directory="templates")
# 活跃连接列表
active_connections = []
# WebSocket 与昵称映射表
usernames = {}
# 首页路由
@app.get("/")
async def get(request: Request):
return templates.TemplateResponse("chat.html", {"request": request})
# WebSocket 路由
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
active_connections.append(websocket)
await broadcast_online_count() # 一连上就广播在线人数
try:
# 接收第一个消息作为昵称
username = await websocket.receive_text()
usernames[websocket] = username
await broadcast(f"[系统]{username} 加入了聊天室")
await broadcast_online_count()
while True:
data = await websocket.receive_text()
await broadcast(f"{username}{data}")
except WebSocketDisconnect:
active_connections.remove(websocket)
left_username = usernames.pop(websocket, "匿名用户")
await broadcast(f"[系统]{left_username} 离开了聊天室")
await broadcast_online_count()
# 广播消息给所有连接
async def broadcast(message: str):
to_remove = []
for connection in active_connections:
try:
await connection.send_text(message)
except:
to_remove.append(connection)
for conn in to_remove:
active_connections.remove(conn)
usernames.pop(conn, None)
# 广播在线人数
async def broadcast_online_count():
message = f"[人数]{len(active_connections)}"
to_remove = []
for conn in active_connections:
try:
await conn.send_text(message)
except:
to_remove.append(conn)
for conn in to_remove:
active_connections.remove(conn)
usernames.pop(conn, None)
if __name__ == "__main__":
uvicorn.run("chat:app", host="0.0.0.0", port=8202)