像UDP一样广播,具有TCP的可靠性

Posted

技术标签:

【中文标题】像UDP一样广播,具有TCP的可靠性【英文标题】:Broadcast like UDP with the reliability of TCP 【发布时间】:2010-09-07 02:10:25 【问题描述】:

我正在开发一个完全在单个网络中运行的 .net 解决方案。当用户对系统进行更改时,我想发布一个公告,让其他人听到并采取相应的行动。有没有一种方法可以让我们广播出这样的消息(就像 UDP 会让你做的那样),同时保持有保证的传输(如 TCP)?

这是在一个小型网络(30 多个客户端)上,如果这会有所作为的话。

【问题讨论】:

【参考方案1】:

几乎所有游戏都需要 UDP 的快速反应特性(在较小程度上还需要无连接特性)和 TCP 的可靠性。他们所做的是在 UDP 之上构建自己的可靠协议。这使他们能够将数据包突发到任何地方,并且还可以选择使它们可靠。

可靠的数据包系统通常是一个简单的重试直到确认系统,比 TCP 更简单,但有些协议远远超出了 TCP 所能提供的范围。

你的情况听起来很简单。您可能能够自己制定最干净的解决方案 - 只需让每个客户端发回“我听到了”响应并让服务器继续尝试直到它得到它(或放弃)。

如果您想要更多内容,大多数自定义协议库都使用 C++,所以我不确定它们对您有多大用处。但是,我在这里的知识是几年前的-也许现在已经移植了一些协议。嗯... RakNet 和 enet 是我想到的两个 C/C++ 库。

【讨论】:

关于“这远远超出了 TCP 所能提供的范围”,既然 TCP 是专门为解决可靠传递问题而设计的,这怎么可能呢? TCP 在可靠的数据包系统中是否缺少某些东西? @Pacerier TCP 将保留它已经收到的旧数据,如果流中缺少一点点。也许在某些情况下,要求是不同的——数据一到就获取,即使它是乱序的。【参考方案2】:

看看sctp,它结合了 tcp 和 udp 功能。有一个窗口implementation 可用。

【讨论】:

+1 用于建议 sctp。但是 sctp 确实没有时间像 TCP 或 UDP 那样成熟。许多驱动程序、网卡和交换机都没有像 TCP 那样对其进行超级优化。这里有一个有趣的性能比较 - datatag.web.cern.ch/datatag/WP3/sctp/tests.htm【参考方案3】:

您可以使用Spread进行群组交流。

【讨论】:

我会支持这个。使用其他人的图书馆是您正确的最佳选择。 @JayKominek,取决于“其他人”是谁。【参考方案4】:

@epatel - 我支持 SCTP 的建议(我投了赞成票,但还不能在这里发表评论)。

SCTP 具有许多出色的功能和灵活性。您可以将连接细分为多个流,并选择每个流的可靠性以及是否有序。或者,使用Partially Reliability 扩展,您可以控制每条消息的可靠性。

【讨论】:

【参考方案5】:

广播不是你想要的。由于可能并且很可能会有连接到该网络的设备不关心您的消息,因此您应该使用多播。与必须向网络上的每个客户端发送并由其处理的广播消息不同,多播消息仅传递给感兴趣的客户端(即那些有意接收这种特定类型的消息并对其采取行动的客户端)。

如果您稍后扩展此系统以使其需要通过大型网络进行路由,则多播可以扩展至此,而广播则不会,因此您获得了可扩展性优势,稍后您可能会意识到这一点。同时,您消除了交换机和其他不需要看到这些“发生了变化”消息的设备的不必要开销。

【讨论】:

您不知道从问题中,例如在无线域中,当消息通过空中发送时,您将被阻止在网络之外,因此广播、阅读总是更有效它并忽略它是微不足道的成本。一些用例运行专用网络,例如矿山、传感器网络、控制系统等 这不是“更高效的广播”,恰恰相反。这就是我的观点。【参考方案6】:

您可能想查看RFC 3208“PGM 可靠传输协议规范”。

这是摘要:

实用通用组播 (PGM) 是一种可靠的多播传输 适用于需要的应用程序的协议 有序或无序, 无重复的多播数据 从多个来源交付到 多个接收器。 PGM 保证 该组中的接收器 接收来自的所有数据包 传输和维修,或者是 能够检测到不可恢复的数据 数据包丢失。 PGM 是专门 旨在作为一个可行的解决方案 具有基本的多播应用程序 可靠性要求。它的中心 设计目标是简单的 操作适当考虑 可扩展性和网络效率。

【讨论】:

【参考方案7】:

您可以使用消息代理,例如 ActiveMQ。 将消息发布到主题并让客户端注册对该主题的持久订阅,这样即使他们不在线也不会错过任何消息。

Apache ActiveMQ 是一个消息代理 用Java编写的完整的 JMS 客户端。然而 Apache ActiveMQ 是 旨在通过数字进行通信 的协议,如 Stomp 和 OpenWire连同支持一个 不同语言特定的数量 客户。

客户端平台支持包括c#和.net

【讨论】:

【参考方案8】:

您可以在应用层实现自己的类似 TCP 的行为。

因此,例如,您会发送 UDP 广播,但随后会期望来自每个主机的回复响应。如果您在 X 秒内没有得到响应,则发送另一个,依此类推,直到达到某种阈值。如果达到阈值(即主机根本没有响应),则报告错误。

不过,要做到这一点,您需要一个预定义的主机列表来期待响应。

【讨论】:

【参考方案9】:

创建一个 TCP 服务器。让每个客户端连接。在您与客户端的 TCP 协议中,使用以下消息的总大小的 2 字节前缀创建每个数据包。

客户端然后在套接字上调用read(max_size=2) 来确定下一条消息的大小,然后read(max_size=s) 来收集消息。

您会收到可靠、有序的消息,而且很简单。您不需要为此使用消息传递框架。

【讨论】:

现在有 30 多个客户,未来会达到几百个。你将如何支持它?【参考方案10】:

肯定想调查Pragmatic General Multicast:

虽然 TCP 使用 ACK 来确认发送的数据包组(这会多播不经济),但 PGM 使用否定确认 (NAK) 的概念。

对于进一步的 G-diving,您要查找的术语是 reliable multicast。也可以看看Multipath TCP。

【讨论】:

【参考方案11】:

您可以做的是在广播之后让 客户端 启动 tcp 连接。否则,您只需保留所有客户端的列表并自己启动与每个客户端的连接。

【讨论】:

【参考方案12】:

从广义上讲,我认为有三种选择:

    您可以创建一个实体(线程、进程、服务器、服务或解决方案中存在的任何事物)来保存订阅者列表并向他们发送单播 UDP 消息,而不是广播 UDP。李> 使用 UDP 多播,但您必须编写某种机制来为您提供可靠的传输(即重试、超时等)。这也意味着您必须得到客户的回复。 如果您不害怕实验性传输协议,您可以向here 寻求建议。,

【讨论】:

【参考方案13】:

Yoy 应该看看 Norm(面向 NACK 的可靠多播)规范。你可以找到information about Norm here。

NORM 协议旨在 提供端到端的可靠传输 大量数据对象或流 通用 IP 多播路由和 转发服务。 NORM 使用 选择性否定确认 (NACK) 传输机制 可靠性并提供额外的 协议机制进行 可靠的多播会话 有限的“先验”协调 发送者和接收者

它在军事界非常有名。

Norm specs.

Norm Source

【讨论】:

【参考方案14】:

如果可以使用库,为什么要从头开始构建?尤其是这么小的项目?

尝试使用Emcaster,它本身使用可靠的多播消息传递 - PGM,它是用 .NET 编写的并具有完整源代码。您将获得带有主题过滤功能的不错的发布/订阅引擎。或者你可以从代码中学习如何做,并以此为基础你自己的扩展。

【讨论】:

【参考方案15】:

我认为在这些场景中 TCP 最令人讨厌的特性是能够将传入数据包按原始顺序排序的能力/方式 - 流的概念。在字节到达之前的字节之前,您无法读取字节。

如果你可以没有它,你就有机会拥有你的协议,快速可靠,但不是为了数据包的排序!根本不可能同时管理它们,因为在收到丢失数据包的另一个副本之前,您无法对字节进行排序,这是主要的权衡。

【讨论】:

【参考方案16】:

进行 RDP 多播。

【讨论】:

没有 TCP 多播,我会投反对票,但我没有足够的声誉。

以上是关于像UDP一样广播,具有TCP的可靠性的主要内容,如果未能解决你的问题,请参考以下文章

网络TCP

tcp和udp的区别

TCP伪装

TCP伪装

TCP/IP 协议图--传输层中的 TCP 和 UDP

网络协议趣谈TCP协议连接和状态