同时使用TCP和UDP是否有意义?


10

读完之后对于大量数据实时游戏,UDP是否仍然优于TCP?,我想知道同时使用TCP和UDP是否有意义,但是对于不同的事物:

  • TCP,用于发送很少发送的信息,但应确保可靠到达。
    例如分数更新,玩家的名字,甚至是游戏世界中灯光的开/关状态。

  • UDP用于传输不断更新的信息,有时可能会丢失,因为总是有更新的信息出现。
    例如位置,旋转度等

这是一个合理的主意吗?可能的缺点是什么?
有更好的方法来解决这个问题吗?


确保阅读本站点上有关udp和tcp的其余线程。您会发现一些实质上可以解决您的问题的细节。作为一个假设:我怀疑存在基于UDP的混合协议,它们试图从两个方面都获得最大收益,即较低的延迟,争用策略,负载平衡和交付保证。根据建议,搜索与该主题相关的问题,并将您的问题缩小到您认为此处尚未解决的问题。
teodron '16

@teodron您不必怀疑。如我的回答所述,这是事实。
工程师

Answers:


8

由于这两个协议之间的争用,这会导致UDP的数据包丢失-请记住,不能保证UDP传递,而TCP可以保证。当UDP受苦时,更多的TCP数据包将通过-TCP导致UDP数据包丢失。(历史性的)想法是,路由器基础结构更倾向于TCP而不是UDP,尽管我怀疑在这一后期阶段这是否仍然正确。

我认为您最好找到一种可以在游戏等中使用的面向连接的UDP协议,该协议为您提供TCP的一些优点,而且没有缺点。有一些这样的方法,通常会在白皮书中详细说明每个概念。

其中的一个示例是开源Enet库,其主要功能是可选的,可靠的,按顺序的UDP数据包传递。


1
为了使答案“更简单”,您能否为基于UDP的传输库提供简短(非常简短)的选项/引用列表?(也许是ENET,RakNet,zeroMQ,UDT?)。根据我上面的评论,我相信我已经在该站点的某个地方看到了有关这些内容的讨论,但是值得复制该信息的一部分。
teodron '16

1
@Arcane工程师如果UDP和TCP套接字在不同的端口上运行怎么办?
KaareZ

@KaareZ不应有任何区别。如果只是简单地分成端口,那么已经完成的研究(请参见编辑链接)将无效。归根结底,端口只是软件端口。它并没有真正影响网络特性,这可以归结为这。
工程师

您说的是有道理的,但我不禁想知道这是否仍然适用于TCP流量很少的情况。如果仅少量信息通过TCP传输,例如平均每10秒发送一次或两次,那是否真的会明显影响UDP流量?
gandalf3 '16

2
“ TCP导致UDP数据包丢失”的文章没有日期。它的最新参考文献来自1996年。该论文何时出版?结论仍然有效吗?
Andreas

4

这是Sam Jansen在gafferongames.com上发表的评论中的一句话

作为网络研究人员而不是游戏开发人员,永远不要同时使用TCP和UDP的结论似乎有些强烈。只有发送太多数据,TCP才会丢失数据包;在某些方面就像您要发送的UDP数据一样。区别在于您无法直接控制TCP的发送速率,这对您是隐藏的。

如果您只需要发送一些可靠的数据,而又不想担心重传和实现可靠的协议,并且知道速率会很低,那么使用TCP和UDP都不会有任何问题。

两者之间的关系并没有那么复杂:TCP仅增加其发送速率(如果有要发送的数据),直到丢失数据包为止,在这种情况下,它回拨其速率,然后再次开始提高速率(这时间更慢)。当它的速率增加导致数据包丢失时,它很可能也击中任何其他数据流,包括UDP数据包。

本文UDP数据包丢失的特点:TCP流量的影响通过一次打开多个TCP连接,并充斥数据网络得到了它的结果。这导致拥塞,随后是全局同步,这两者都会导致数据包丢失。显然,游戏客户端不会一次打开十几个连接并向网络中填充数据,因此您的结果将有所不同。

要回答您的问题:

我想知道同时使用TCP和UDP是否有意义,但是对于不同的事情[...]

是的,假设您不超出带宽限制,这是可以接受的事情。

  • TCP,用于发送很少发送的信息,但应确保可靠到达。例如分数更新,玩家的名字,甚至是游戏世界中灯光的开/关状态。

当同时使用TCP和UDP时,您应该始终希望通过UDP发送尽可能多的数据,而通过TCP发送尽可能少的数据。

现在,我问你一个问题:是否真的有必要通过TCP发送比分,球员的姓名和指示灯状态?虽然确实需要最终接收这些数据,但是是否确实需要严格按顺序并且仅一次接收这些数据呢?

可能不是。

UDP在这些情况下可以正常工作,而Quake 3是一个很好的例子。

那么,什么是将TCP与UDP一起使用的好例子呢?好吧,想想一个游戏的聊天框。此聊天框的更新(即,新的文本行)需要可靠且严格按顺序发送。因此,TCP非常适合。


3

这是一个合理的主意吗?

可能的缺点是什么?

  • 数据包丢失,更多的代码复杂性,另一个需要管理的连接==断开连接,超时,异常的可能性更大,无论...

有更好的方法来解决这个问题吗?

  • 使用现有的可靠UDP库。最受欢迎的两个是:Lidgren Network(C#),RakNet(C ++)。根据经验,我可以说Lidgren非常易于使用,快速且可靠。

1

还有其他资源限制要考虑。服务器上TCP的大多数实现(我相信所有,但没有参考)都限制了服务器可以同时打开多少个并发TCP连接。如果每个玩家需要自己的连接,这将限制您可以同时打开的玩家数量。

限制由网络系统中的设置定义。此外,每个Connection都会占用一些内存,这些内存必须来自服务器上的某个位置。

一种解决方案是仅在传输数据时打开一个临时TCP连接,然后立即关闭它。这将使事务变慢,打开tcp连接是一个相当“昂贵”的过程。与往常一样,从一开始就设计一个强大的系统以实现巨大的增长。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.