i007.cc

i007.cc

优先队列-降维打击

05.价值资料

Websocket是什么?解决了什么问题?对于网络游戏来讲,用Websocket合适么?会有哪些优势和劣势?

WebSocket 是一种网络通信协议,建立在 TCP 之上,允许浏览器(或其他客户端)和服务器之间维持一条持久的、全双工的连接。它和 HTTP 有关系但不是一回事:建立连接时会先发一次 HTTP 请求(带有 Upgrade: websocket 头),服务器同意后就把这条 TCP 连接”升级”成 WebSocket 连接,之后双方就可以随时互相发数据,不用再重新握手。协议本身在 RFC 6455 里定义,默认用 ws:// 或加密的 wss:// 作为 URL scheme。

它主要解决的问题是传统 HTTP 通信模式在实时交互场景下的局限性。HTTP 是请求-响应模式,天生是客户端主动发起、服务器被动应答,服务器没法主动”推”数据给客户端。在 WebSocket 出现之前,要做类似聊天室、实时通知这种需要服务器主动推送的功能,常见做法是轮询(客户端每隔几秒就发一次请求问”有新消息吗”)或者长轮询(服务器把请求挂起,等有数据了才响应),这两种方式都很浪费资源:轮询会产生大量无意义的请求和延迟,长轮询虽然好一些,但每次响应完还要重新建立连接,而且每次请求都要带着完整的 HTTP 头,开销不小。

WebSocket 用一条长期保持打开的连接取代了这些方案。连接建立之后,服务器和客户端都能随时主动发消息,不需要每次都重新发起 HTTP 请求,也不用带那么多头部信息,所以延迟低、开销小,特别适合需要频繁双向通信的场景,比如网页聊天、在线协作编辑、股票行情推送、多人游戏、实时通知系统等。

简单说,HTTP 解决的是”客户端要什么就问服务器要什么”的问题,而 WebSocket 解决的是”双方需要随时互相通知对方”的问题。


这个要分游戏类型来看,不能一概而论。

WebSocket 基于 TCP,而 TCP 最大的特点是可靠传输:它保证数据包按顺序到达,丢了会自动重传。这个特性对某些游戏类型是优势,对另一些则是明显的劣势。

对于回合制游戏、卡牌游戏、棋牌类、MOBA 里的非战斗逻辑(聊天、商城、排行榜、匹配系统)、以及大多数网页游戏来说,WebSocket 是很合适的选择。它相比传统的 HTTP 轮询延迟低得多,服务器能主动推送状态变化,实现简单,浏览器原生支持不需要额外插件,而且能直接复用 HTTP 的基础设施,比如通过 wss:// 走 443 端口,容易穿过防火墙和代理,也方便加 TLS 加密。很多网页版的 MMORPG、卡牌对战、以及 Agar.io 这类简单的多人网页游戏都在用 WebSocket。

但对于需要高实时性的动作类游戏,尤其是第一人称射击、格斗游戏、竞速游戏这种对延迟极度敏感、每秒要同步几十次玩家位置和动作的场景,WebSocket 的短板就暴露出来了。核心问题是 TCP 的可靠性和顺序保证在这里反而成了负担,这就是所谓的”队头阻塞”(head-of-line blocking):如果一个数据包丢了,TCP 会暂停后面所有已经到达的包,一直等到丢的那个包重传成功为止。对于实时游戏来说,一个 100 毫秒前的位置更新包丢了并不重要,玩家早就移动到新位置了,重传旧数据反而没有意义,但 TCP 还是会强行帮你补上,导致后续数据全部卡住,造成明显的卡顿或者”倒退”感。这类游戏通常更希望用 UDP,允许丢包、不保证顺序,因为新的状态数据很快就会覆盖旧的,快速把最新数据传过去比保证每个包都到更重要。

另外 WebSocket 因为跑在 TCP 加 HTTP 握手之上,连接建立的开销也比原生 UDP 大一些,虽然一旦建立之后这个差异影响不大。

所以行业里的实际做法通常是分层的:核心的实时对战逻辑,尤其是需要极低延迟的部分,用 UDP 或者基于 UDP 的自定义可靠层(比如 QUIC,或者游戏引擎自己实现的可靠 UDP),而聊天、匹配、商城、排行榜这些对延迟没那么敏感、但需要可靠传输的部分,用 WebSocket 或者干脆用 HTTP。像 Unity、Unreal 这些主流引擎的多人游戏方案,底层网络大多是 UDP。但如果目标平台是浏览器(不能直接用原生 UDP socket),情况就不一样了:这时候要么用 WebSocket 承受一定的延迟代价,要么用 WebRTC 的 DataChannel,它可以配置成不保证顺序、不要求可靠传输,行为更接近 UDP,是浏览器里对实时性要求高的游戏更好的选择。

简单总结一下:WebSocket 适合对延迟要求不那么苛刻、又需要数据可靠到达的游戏和游戏子系统;不适合需要极致低延迟、能容忍丢包的动作类实时对战核心逻辑,这类场景更适合 UDP 或 WebRTC DataChannel。

发表回复