游戏卡顿白皮书 › 只有部分人遇到的问题
固定 UDP 端口冲突 Two clients bound to the same local UDP port
原因 ID pt-port-collision · 主责 研发团队·客户端开发 · 配合 研发团队·服务器开发
在含图示和实验的完整版中打开此卡片 →
客户端被做成使用固定的本地端口时,同一台电脑上的第二个客户端要么用不了这个端口,要么和第一个客户端分着收包。
起因 两个客户端要打开同一个本地 UDP 端口(用重用选项强行共用) → 结果 OS 只把收到的包交给其中一个 socket,或不保证由哪一个接收。路由器和服务器也把两个客户端看成同一个地址 → 画面表现 一边收不到世界数据包,看不到 NPC 和其他玩家,或者掉线
- 症状
- 隐身/幽灵实体, 掉线, 连不上/无限加载
- 因素
- 丢包
- 谁会遇到
- 双开时只有一个客户端
- 何时出现
- 刚登录/维护结束后, 一直
- 负责方
- 主责 研发团队·客户端开发 · 配合 研发团队·服务器开发
- 研发团队要做的事
- 客户端:本地端口由 OS 自动选择(bind 0 号端口)。服务器:用每个连接签发的会话令牌区分连接。
- 监控图上
- 仅部分偏高 · 各客户端收到的包数
- 查看位置
- 在玩家电脑上开着两个客户端,在命令提示符中用 netstat -ano -p udp 查看每个游戏进程(PID)打开的本地 UDP 端口。在服务器侧确认两个会话是否来自同一公网 IP、同一端口
- 确认依据
- 两个游戏进程绑定在同一个本地端口上,或在服务器上两个会话显示为同一 IP、端口。只开一个就正常
- 排除依据
- 两个客户端用的是不同的本地端口,一边仍然异常,看“按 IP/设备区分会话的 bug”或“多开限制”
- 确认手段
- 需在玩家侧环境确认
出处
- Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSE Microsoft
用 SO_REUSEADDR 对同一端口第二次 bind 会抢走端口,无法确定哪个 socket 收包 - bind function (winsock.h) Microsoft
把端口设为 0 来 bind,会从动态端口范围(49152~65535)中分配一个唯一端口 - netstat Microsoft
-a 显示 TCP、UDP 端口,-n 显示数字地址,-o 显示进程 ID(PID),-p udp 只显示 UDP
相关原因
同一层:只有部分人遇到的问题
其他层中同样导致“隐身/幽灵实体”的原因
查看含图示和实验的原卡片