Python 使用tcp重传的可靠udp

Python 使用tcp重传的可靠udp,python,c++,Python,C++,我是发送服务器发送的UDP多播数据(证券交易所数据)的客户端接收器。我正在连续接收udp多播数据包流,该数据包流按顺序编号为1到大约35000000,在6小时内统一发送。我需要确保在每256个数据包之后周期性地处理N个数据包之前,接收到所有高达N个的数据包。i、 我需要可靠的UDP 使用TCP重传模拟可靠的UDP。如果任何udp数据包丢失/未收到,则通过指定所需的丢失数据包范围(起始编号、结束编号),使用tcp协议请求该数据包。 发送方保存迄今为止通过UDP多播发送的所有数据包(证券交易所数据)

我是发送服务器发送的UDP多播数据(证券交易所数据)的客户端接收器。我正在连续接收udp多播数据包流,该数据包流按顺序编号为1到大约35000000,在6小时内统一发送。我需要确保在每256个数据包之后周期性地处理N个数据包之前,接收到所有高达N个的数据包。i、 我需要可靠的UDP

使用TCP重传模拟可靠的UDP。如果任何udp数据包丢失/未收到,则通过指定所需的丢失数据包范围(起始编号、结束编号),使用tcp协议请求该数据包。 发送方保存迄今为止通过UDP多播发送的所有数据包(证券交易所数据)的记录。因此,发送方将仅通过TCP重新发送接收方通过TCP专门请求的数据包编号。这就是接收机实现UDP可靠性的方式。UDP丢弃率非常小(小于0.001%),除非在一天中启动UDP多播,在这种情况下,所有先前发送的UDP数据包从1到N都需要在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,…}

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

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

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

我写了一篇文章,它基本上使用了您描述的技术(多播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()内很难完全关闭)

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

  • 如果你真的想变得有趣,你可以研究编码数据acr的算法