使用UDP,您可以控制“连接状态”,这几乎是进行任何点对点相关操作的最佳方式,
如果您拥有大量节点或关心带宽、内存和CPU开销。通过将所有与每个节点的“连接状态”相关的控制移动到您的应用程序中,您可以最小化浪费资源的数量,使其完全符合您的需求。
您将绕过许多特定于操作系统的怪异问题,这些问题限制了TCP在高连接数下的有效性。 TIME_WAIT膨胀和数十到数百个需要为每个P2P应用程序用户进行调整的特定于操作系统的设置。我制作的一个测试应用程序允许您使用带有确认或TCP的UDP,无论使用UDP的操作系统如何,性能差异仅有10%。 TCP的性能始终低于最佳UDP,其性能变化范围高达600%,具体取决于操作系统。通过调整,您可以使大多数操作系统使用TCP大致相同,但默认情况下,大多数操作系统没有正确调整。
因此,在我看来,与TCP相比,创建可靠的UDP P2P网络更加困难,但通常是必要的。但是,我只建议您采用这种方法,如果您在网络方面非常有经验,因为有许多需要处理的“陷阱”。有一些库可以帮助处理此类问题,例如Raknet或Enet。它们提供了使用可靠的UDP的方法,但仍需要更高的网络知识才能知道所有这些内容如何相互关联,而对于TCP,大部分都是隐藏的。
在点对点网络中,您经常会收到像NODE PING这样的消息,您可能并不关心每个消息是否始终被接收,您只关心最近是否收到过一条消息。也就是说,您可以每10秒发送一次ping,并在60秒内未收到ping后断开该节点。这意味着您需要连续6个ping数据包失败,这是极不可能发生的,除非该节点真的已关闭。如果在该60秒期间收到了至少一个ping,则该节点仍处于活动状态。如果使用TCP实现这一点,则会涉及更多的延迟和带宽,因为它确保每个ping消息都通过,并将阻止任何其他数据出去,直到它通过。由于您不能依赖TCP可靠地告诉您连接是否已断开,因此您被迫添加类似的PING功能以用于TCP,除了TCP已经在处理数据包的所有其他额外事项之外。
游戏通常还有一些数据,如果客户端没有接收到它,那么没有关系,因为几毫秒后会有更多的数据包到来,这将使任何遗漏的数据包无效。也就是说,玩家在1秒钟内从A移动到Z,他的客户端每40毫秒发送一次更新,ABCDEF G__I__KLMNOPQRSTUVWXYZ。如果我们错过了“H和J”,是否真的很重要?不太重要,这就是预测可以发挥作用的地方,但这通常与大多数P2P项目无关。如果那是TCP而不是UDP,则会增加带宽要求,并为接收到的其他数据包添加延迟,因为数据将被重新发送,直到它到达,除了它已经通过确认添加的额外延迟。
基本上,你可以使用UDP降低点对点网络中许多消息的延迟和网络开销。然而,总会有一些消息是需要可靠发送的,这就要求你基本上实现一些可靠的方式将数据包发送到该节点,类似于TCP。如果你想要一个可靠的点对点网络,那么你需要一定的专业知识。一些需要研究的事情包括用数字排序数据包、消息ACK等。
如果你非常关心效率或者确实需要成千上万的连接,那么在UDP中实现你的特定协议总是比TCP更好。但是也有TCP的使用场景,比如如果项目的时间很重要,或者你是网络编程的新手。