在 UDP 数据包中实现某种程度的可靠性是否会超过使用 TCP 的目的?

网络工程 通讯协议 UDP 第4层
2021-07-26 07:43:52

考虑到 UDP 数据包可能会丢失或延迟到达目标目的地,是否更有意义:

  • 将 TCP 套接字用于重要的消息和事件(例如:在游戏中,玩家被击中、攻击、死亡、捡起物品、拯救公主等),

    或者...

  • 是否应该在您的 UDP 数据包结构中开发某种“可靠性系统”以确认这些特定事件的接收?

似乎,至少,对于 TCP 在 UDP 上的几个字节差异(64b 与 52b 的最小值,因此相距 12b,根据这个答案:https : //stackoverflow.com/a/1846139/468206)它让 TCP 连接处理这些事件而不是在 UDP 中重新发明轮子会更有意义。但也许我没有抓住重点?

长期保持 TCP 连接/应用程序/游戏的持续时间(假设至少 15 分钟)是否会应用一些不易减少或控制的开销以及定制的“可靠”UDP执行?

UDP 中的字节节省是否会更明显,因为例如,所讨论的可靠事件消息可能带有一些不可靠的数据?(不可靠的数据 = 基本上任何通常会忽略发送额外“可靠性”字节的数据,使用即发即弃的方法)?

注意:我可能忘记或没有考虑 TCP 的某些方面,这就是为什么我联系您可爱的经验丰富的网络开发人员,以帮助提出这一点并将其带回家!:)

2个回答

考虑到 UDP 数据包可能会丢失或延迟到达目标目的地,是否更有意义: 使用 TCP 套接字处理重要的消息和事件(例如:在游戏中,玩家被击中、攻击、死亡、捡起物品、拯救公主等),

或者...是否应该在您的 UDP 数据包结构中开发某种“可靠性系统”以确认这些特定事件的接收?

简而言之,两者都不是。

网上有很多资源都在讨论这一点(实时协议设计,尤其是在游戏中),但总而言之,一个主机充当“服务器”并跟踪游戏状态(所有玩家、统计数据和对象)的模型状态),所有客户端通过 UDP 与服务器通信是行业标准。

使用 UDP 连接是因为您否定了与连接设置或分段确认相关的任何往返延迟。

因为你有一个服务器跟踪状态,它不需要关心客户端是否接收帧 - 客户端和服务器只发送增量,然后它们从最后一个已知状态更新。

这当然是对一个非常复杂的主题的过度简化,但要点是不需要在 UDP 的顶部对上层协议进行黑客攻击以使其“可靠”——实时流量的本质,如果不是在很短的时间内交付,它就毫无价值。

我强烈推荐以下文章,讨论 John Carmack 在编写 Quake 3 网络代码时的实验和观察:

http://trac.bookofhook.com/bookofhook/trac.cgi/wiki/Quake3Networking

大小开销可以忽略不计。发送 acks 不会阻止将数据传送到应用程序。对于保持会话长时间打开的游戏,连接建立时间可以忽略不计。

TCP 的真正问题是线头阻塞。如果单个数据包在 TCP 连接上丢失,则必须检测丢失,必须将重新发送的数据包和重新发送的数据包传送到应用程序,然后才能将丢失的数据包之后的任何数据传送到应用程序。

可以在不阻塞线路的情况下实现某种程度的可靠性,这就是我希望任何明智的实时游戏开发人员都能做到的。

实时性不那么重要的游戏可以通过使用 TCP 逃脱。