
总览
这个横型是基于个后台,websocket ,python ,和一个index.html网页。
一开始AI,给出的是,Node.js的server.js文件。但是也轻易换成了python.他想用vue,和其他框架,我说先不用了,我测下通道。于是有了下午8小时的折腾。
我说下,基于ddnsto是实现放在互联网上的,虽然他只支持http,内总,+https外部。
这里我重点说下,外总的,https,透传是如何代理websocket r wss://协议的。这个很有看头。我最后会提供全部代码,在资源中,
分步
- 安装docker docker-compose
- 安装filebrowser.容器
- 建立源码目录和python 3.11容器,开通,static,和,websocket服务
- 安装NginxUI,和配置反代,主要是websocket.到子目录
核心坑
- 安装docker时用了国内的几个镜像,在debian下安装的,镜像好像不行,用某问,原厂的安装过程,居然速度很快,也就是docker 可能活着。
- 拉镜像必须用几个,国内的源,因为有的好几百M,难用的很慢。
- 前面说了,filebrowser的密码要改短点,不然真难用,不安全用长度解决。不能用机制的吗?比如把强试的路档死呢?也许档不死吧。这个项目说要停止维护,要找个第三方。它主要用来在线写和改文件。 目录的权力分配好像不太好把握。测试就无所谓,生产要慎重。
- 我定制了,python启动代码。 让,8000的http.server做保底。在启动后,docker exec -it 用python server.py咆主程序。
- 要在本地咆通,需要在insex.html中的 WS_URL 定制成自已的IP。并在布署到ddnsto后,改成域名的地址,这是new WebSocket (WS_URL)的握手地址。
- nginx proxy manager 这个NPM 不是我的菜,因为太大,拉起来费劲,NginxUI小很多是go 的。在安装时,10分钟有效会在,内决/etc/nginxUI/.installsecret. 这个是进入的第一次的凭证。一开始没上官网,没有找到,全程在AI聊天。 这个已经在开始yaml compse 中指向了外部data.
- ws到子目录的nginx反代,这个是最后一个。 在新建站点时,关注点在于,把/ws/这个location定义成,
bash
'` location /ws/ {
proxy_pass http://127.0.0.1:3000/; # 替换为你的后端服务地址
# ✨ WebSocket 核心三件套(必须添加)
proxy_http_version 1.1; # 1. 必须使用 HTTP/1.1 版本
proxy_set_header Upgrade $http_upgrade; # 2. 透传客户端的 Upgrade 头
proxy_set_header Connection "upgrade"; # 3. 明确指示协议升级
# 传递真实客户端信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# ⏱️ 长连接超时控制(极其重要)
proxy_read_timeout 3600s; # 默认60秒太短,WebSocket长连接必须调大
proxy_send_timeout 3600s;
}
"
站点要先保存,再启用,基本上可以用,在配置管里中,要把原来80换走,走为容器只转出了,80,9000, 要是不想再启动一次,需要让出,80-到9000管理口的转发。
说了这么多,
就能上云了,
上云时需要扫一下微信,就会转到,工作台了。
在云上
为了做测试,在云上的速度,需要在ddnsto开通一个二级域名到家中接口docker, nginx反代服务的转发。
先去安装一下,ddnsto。 控制台会有安装方法,Docker , Nas, Openwrt. 这是主流的三种安种环境。完成的后的配置是一步到位的。但是有个巨大的能力短板, 谁开通谁用。也就是这个二级域名,好像是专门绑定微信的。 试用是免费7天,
用我的可以免3个月,可以和我交流用起来的感受。
https://web.kooldns.cn/app/#/login?aff=I4D8SPM1
源码我上传到资源,
我一步到位,全部上传吧,这是8小时的工作成果。测了网速可以落子。
全打包资源,不一对一讲解
https://download.csdn.net/download/wjcroom/93388118
bash
import asyncio
import json
import time
import websockets
# 存储当前所有在线的客户端和房间信息
# 格式: {room_id: {player_id: websocket}}
rooms = {}
async def handle_client(websocket):
"""处理单个客户端的连接与消息"""
room_id = None
player_id = None
try:
async for message in websocket:
try:
data = json.loads(message)
action = data.get("action")
# 1. 加入房间
if action == "join":
room_id = data.get("roomId")
player_id = data.get("playerId")
if room_id not in rooms:
rooms[room_id] = {}
rooms[room_id][player_id] = websocket
# 通知房间内其他玩家有新成员加入
await broadcast(room_id, {
"action": "system",
"message": f"玩家 {player_id} 加入了房间"
}, websocket)
# 2. 游戏操作(落子、悔棋等)
elif action == "move":
if room_id and room_id in rooms:
# 将落子数据转发给同房间的其他玩家
await broadcast(room_id, {
"action": "move",
"playerId": player_id,
"row": data.get("row"),
"col": data.get("col"),
"timestamp": data.get("timestamp")
}, websocket)
# 3. 性能测试(Ping-Pong)
elif action == "ping":
await websocket.send(json.dumps({
"action": "pong",
"clientTime": data.get("clientTime"),
"serverTime": int(time.time() * 1000)
}))
except json.JSONDecodeError:
await websocket.send(json.dumps({"error": "无效的 JSON 格式"}))
except websockets.exceptions.ConnectionClosed:
print(f"客户端断开连接: {player_id}")
finally:
# 客户端断开时,从房间中移除
if room_id and player_id and room_id in rooms:
if player_id in rooms[room_id]:
del rooms[room_id][player_id]
await broadcast(room_id, {
"action": "system",
"message": f"玩家 {player_id} 离开了房间"
})
# 如果房间空了,清理房间
if not rooms[room_id]:
del rooms[room_id]
async def broadcast(room_id, message, sender_socket=None):
"""向房间内除发送者外的所有客户端广播消息"""
if room_id not in rooms:
return
msg_str = json.dumps(message)
tasks = []
for pid, ws in rooms[room_id].items():
if ws != sender_socket:
tasks.append(ws.send(msg_str))
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
async def main():
"""启动 WebSocket 服务器"""
print("🚀 五子棋信令服务器已启动,监听端口 3000...")
async with websockets.serve(handle_client, "0.0.0.0", 3000):
await asyncio.Future() # 永久挂起,保持服务器运行
if __name__ == "__main__":
asyncio.run(main())