|
您遇到的错误信息表明您尝试用 curl 直接访问 WebSocket 服务器,但 WebSocket 协议需要特殊的握手过程,而普通 HTTP 客户端(如 curl 或浏览器)无法直接完成这个协议升级过程。以下是详细分析和解决方案: 1. 错误原因分析[size=0.8125]WebSocket 协议特性
WebSocket 连接需要从 HTTP 升级而来,客户端必须发送带有 Upgrade: websocket 和 Connection: Upgrade 头的特殊 HTTP 请求。普通 HTTP 客户端(如 curl)默认不会发送这些头信息。 [size=0.8125]curl 的默认行为
当您执行 curl http://localhost:2700 时: - curl 发送的是普通 HTTP GET 请求
- 服务器期望收到 WebSocket 握手请求
- 由于缺少必要头信息,服务器拒绝连接
- 返回的错误信息中明确提示:"You cannot access a WebSocket server directly with a browser"
2. 正确测试方法方案1:使用 WebSocket 专用客户端工具推荐使用以下工具测试 WebSocket 连接: 工具名称 安装命令(Linux) 使用示例
websocat sudo apt install websocat websocat ws://localhost:2700
wscat npm install -g wscat wscat -c ws://localhost:2700
示例(使用 websocat): - echo "test message" | websocat ws://localhost:2700
复制代码 方案2:使用 curl 的 WebSocket 模式(需要 7.66.0+ 版本)如果您坚持使用 curl,需要指定 WebSocket 模式: - curl --include \
- --no-buffer \
- --header "Connection: Upgrade" \
- --header "Upgrade: websocket" \
- --header "Host: localhost:2700" \
- --header "Sec-WebSocket-Version: 13" \
- --header "Sec-WebSocket-Key: $(openssl rand -hex 16)" \
- http://localhost:2700
复制代码 方案3:修改服务器代码添加调试端点建议在服务器端添加一个普通 HTTP 端点用于调试: - from fastapi import FastAPI
- from fastapi.websockets import WebSocket, WebSocketDisconnect
- import uvicorn
- app = FastAPI()
- @app.get("/")
- async def health_check():
- return {"status": "ok", "protocol": "WebSocket server is running"}
- @app.websocket("/ws")
- async def websocket_endpoint(websocket: WebSocket):
- await websocket.accept()
- try:
- while True:
- data = await websocket.receive_text()
- await websocket.send_text(f"Echo: {data}")
- except WebSocketDisconnect:
- print("Client disconnected")
- if __name__ == "__main__":
- uvicorn.run(app, host="0.0.0.0", port=2700)
复制代码
3. 验证步骤 先测试 HTTP 端点: - curl http://localhost:2700/
- # 应返回:{"status":"ok","protocol":"WebSocket server is running"}
复制代码再测试 WebSocket 连接: - websocat ws://localhost:2700/ws
- # 输入测试消息后应收到回声响应
复制代码 4. 常见问题排查表现象 可能原因 解决方案
curl 返回 404 未正确处理 HTTP 请求 添加 /health 等调试端点
连接立即关闭 缺少 Sec-WebSocket-Accept 头 使用专业 WebSocket 客户端
"Connection refused" 服务未运行 检查服务日志 journalctl -u your_service
"Timeout during handshake" 防火墙阻止 检查 iptables/nftables 规则
5. 最佳实践建议- 开发环境:始终保留一个 HTTP 调试端点
- 生产环境:
- 使用 Nginx 作为反向代理处理 WebSocket
- 配置健康检查端点 (nginx)
- location /health {
- return 200 "ok";
- add_header Content-Type text/plain;
- }
- location /ws {
- proxy_pass http://backend:2700;
- proxy_http_version 1.1;
- proxy_set_header Upgrade $http_upgrade;
- proxy_set_header Connection "Upgrade";
- }
复制代码 您当前的错误完全符合预期行为,因为 WebSocket 需要特殊的协议升级流程。建议使用 websocat 或 wscat 进行测试,这些工具会自动处理所有必要的协议头信息。
|