Websocket 在连接到 FastAPI 端点后立即关闭

Websocket getting closed immediately after connecting to FastAPI Endpoint

我正在尝试将 websocket aiohttp 客户端连接到 fastapi websocket 端点,但我无法发送或接收任何数据,因为 websocket 似乎在连接到端点后立即关闭。


服务器

import uvicorn
from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket('/ws')
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    ...


if __name__ == '__main__':
    uvicorn.run('test:app', debug=True, reload=True)

客户端

import aiohttp
import asyncio

async def main():
    s = aiohttp.ClientSession()
    ws = await s.ws_connect('ws://localhost:8000/ws')
    while True:
        ...

asyncio.run(main())

当我尝试在建立连接后将数据从服务器发送到客户端时

服务器

@app.websocket('/ws')
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    await websocket.send_text('yo')

客户端

while True:
   print(await ws.receive())

我总是在客户的控制台中打印出来

WSMessage(type=<WSMsgType.CLOSED: 257>, data=None, extra=None)

在服务器的调试控制台中显示

INFO:     ('127.0.0.1', 59792) - "WebSocket /ws" [accepted]
INFO:     connection open
INFO:     connection closed

当我尝试从客户端向服务器发送数据时

服务器

@app.websocket('/ws')
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        await websocket.receive_text()

客户端

ws = await s.ws_connect('ws://localhost:8000/ws')
await ws.send_str('client!')

没有任何反应,我在服务器的控制台中没有打印出任何消息,只有调试消息说客户端已被接受,连接打开并再次关闭。


我不知道我做错了什么,我按照 fastAPI 文档中的 this 教程进行操作,其中的 js websocket 示例完全正常。

连接已被任一端(客户端或服务器)关闭,如您的代码片段所示。您需要在服务器和客户端中都有一个循环,以便能够等待消息并连续发送消息(看看 here and here)。

此外,根据 FastAPI's documentation

When a WebSocket connection is closed, the await websocket.receive_text() will raise a WebSocketDisconnect exception, which you can then catch and handle like in this example.

因此,在服务器端,您应该使用 try-catch 块来捕获和处理 WebSocketDisconnect 异常。下面是一个工作示例,演示了客户端(在 aiohttp 中)- 服务器(在 FastAPI 中)使用 websockets 的通信:

服务器

from fastapi import FastAPI, WebSocket, WebSocketDisconnect

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    # await for connections
    await websocket.accept()
    
    try:
        # send "Connection established" message to client
        await websocket.send_text("Connection established!")
        
        # await for messages and send messages
        while True:
            msg = await websocket.receive_text()
            if msg.lower() == "close":
                await websocket.close()
                break
            else:
                print(f'CLIENT says - {msg}')
                await websocket.send_text(f"Your message was: {msg}")
                
    except WebSocketDisconnect:
        print("Client disconnected")   

客户端

import aiohttp
import asyncio

async def main():
    async with aiohttp.ClientSession() as session:
        async with session.ws_connect('ws://localhost:8000/ws') as ws:
            # await for messages and send messages
            async for msg in ws:
                if msg.type == aiohttp.WSMsgType.TEXT:
                    print(f'SERVER says - {msg.data}')
                    text = input('Enter a message: ')
                    await ws.send_str(text)
                elif msg.type == aiohttp.WSMsgType.ERROR:
                    break

asyncio.run(main())