使用tcp重传的可靠udp

2024-04-18 05:02:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我是发送服务器发送的UDP多播数据(证券交易所数据)的客户端接收器。我连续接收udp多播数据包流,序列号为1到大约35000000,在6小时内统一发送。我需要确保所有到N个包都被接收到,然后在每256个包之后周期性地处理N个包的集合。i、 我需要可靠的UDP。你知道吗

使用TCP重传模拟可靠的UDP。如果任何udp数据包丢失/未收到,则使用tcp协议通过指定所需的丢失数据包范围(起始编号、结束编号)来请求。 发送方记录了迄今为止通过UDP多播发送的所有数据包(证券交易数据)。因此,发送方将只通过TCP重新发送接收方通过TCP特别请求的那些数据包号码。这就是接收端实现UDP可靠性的方式。UDP丢弃率非常小(小于0.001%),除非在中午启动UDP多播,在这种情况下,所有以前从1到某些N发送的UDP数据包都需要在TCP上重新发送,当接收到UDP多播数据包N+1之后的实时传输时。)我不能请求发送方(证券交易所)更改其协议--它是固定的。你知道吗

什么是有效的算法来实现这方面的CPU? 问题是速度。我可以使用几个嵌套的循环和方法来创建一个简单的算法,但它不一定是最好的。你知道吗

我正在考虑保留一个数字N来确认我已经收到UDP 数据包1到N,以及不是下一个预期数据包N+1的任何数据包M将被缓冲,例如256个数据包,然后TCP将被用来请求丢失的数字。然后,在TCP请求被填充之后,正常的UDP接收从最后确认的接收号码恢复过来。你知道吗

示例: 假设接收方接收到的UDP数据包的序列为{1,2,3,6,7,8,9,10…} 在第3包之后,下一个包是第6包。数据包4到5丢失。 因此,丢失的数据包{4,5}是使用TCP请求({4到5})请求的,{6,7,8,9,10}是缓冲的。10GBaseT LAN卡上有足够的空间来缓冲35000000个数据包。 所以:接收UDP{1,2,3},通过TCP请求{4,5}重新填充,继续接收UDP{6,7,8,9,10,…}


Tags: 数据算法协议客户端数字数据包编号号码
1条回答
网友
1楼 · 发布于 2024-04-18 05:02:08

我假设由于您使用的是多播,因此将有多个接收器接收这些数据?(因为如果不是这样的话,您可能会改用单播)

因此,如果接收器可以选择请求TCP重新传输他们没有得到的数据包,这意味着传输程序将需要在内存中保留最近发送的UDP数据包的副本,这样当它接收到重新传输请求时,它将有请求的数据可供重新传输。假设您用一个唯一的ID标记每个数据包,它可以将这些数据存储在std::mapstd::unordered_map或类似格式中,以便快速查找。你知道吗

真正的问题是,发送器应该保留多少旧包数据?理想情况下,它会保留所有的信息,因为您永远不知道给定的接收者可能错过了多少信息,也可能想要请求多少信息;但这需要无限的内存,所以这不是一个现实的选择。也许你能做的最好的事情就是决定你愿意为此目的占用多少RAM,并记录下你的表中的字节总数,当它达到限制时,开始从表中删除最旧的数据包,以便将它的大小保持在限制之下。你知道吗

我编写了一个open-source library,它基本上使用了您描述的技术(多播UDP+TCP重新传输以从数据包丢失中恢复)来尽可能快地跨多个主机同步数据库;在实现它的过程中,我学到了一些东西,包括:

  • 如果/如果可以,请将数据消息打包成更大的数据包,最多可达正在传输的网络的MTU(例如,IPv4/以太网为1388字节)。非常小的数据包大小(如48字节/数据包)是低效的,因为固定大小的数据包报头在发送/接收的总数据中占较大的百分比。

  • 只有在发送套接字指示可以写入时才尝试发送。(也就是说,不要假设你永远不会填满套接字的输出数据缓冲区;如果你的流量是“突发的”,你可能会在某个时候)

  • 使UDP套接字的发送和接收缓冲区尽可能大,从而最大限度地减少UDP数据包丢失

  • 通过在专用的高优先级线程中进行所有UDP接收,进一步减少UDP数据包丢失(然后可以将接收到的UDP数据路由回正常优先级线程进行进一步处理主要是避免接收UDP套接字的传入数据缓冲区溢出(如果可能)

  • 对于TCP重传部分,请记住,在最坏的情况下,TCP流可能会减慢到接近零字节/秒,这使得确保客户端A的TCP性能不佳不会阻止与客户端B、C、D之间的TCP通信非常重要,这可以通过非阻塞I/O和select()(或poll()或类似的方式)或异步网络,或通过多个线程来实现;避免阻塞I/O,除非您要实现每个套接字的线程模型(也可能避免该模型,因为在-recv()内无限期阻塞的线程很难完全关闭)

  • 想一想在什么情况下(如果有的话),客户根本不接收特定的数据包是可以接受的;有没有这样的情况?或者整个系统必须停止,直到每个接收器都接收到组中的每个数据包,而不管这可能需要多长时间?

  • 如果你真的想弄明白,你可以研究跨数据包编码的Forward Error Correction算法,这样即使接收器从未接收到数据包(高达一定百分比),它仍然可以解码所有的数据。这使得不太可能需要重新传输请求,代价是使所有数据包稍微变大。

相关问题 更多 >