Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/lua/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Python套接字每秒发送100个UDP数据包,如何减少延迟?_Python_Windows_Sockets_Udp_Latency - Fatal编程技术网

使用Python套接字每秒发送100个UDP数据包,如何减少延迟?

使用Python套接字每秒发送100个UDP数据包,如何减少延迟?,python,windows,sockets,udp,latency,Python,Windows,Sockets,Udp,Latency,我正在通过网络编写一个实时音频共享工具,我首先尝试使用UDP数据包(稍后我将使用TCP进行研究,但我首先希望看到使用UDP可以获得的最佳效果) 在下面的代码中,txmax是在已发送的最后100个数据包中发送单个UPD数据包(大小约1800字节)所花费的最大时间。我观察到: txmax通常在6毫秒到20毫秒的范围内,这是正常的 但是每分钟有一到两次,txmax峰值为250毫秒,即至少有一个sock。sendto(…)发送一个1.8 KB的UDP数据包需要250毫秒 问题:原因可能是什么?如

我正在通过网络编写一个实时音频共享工具,我首先尝试使用UDP数据包(稍后我将使用TCP进行研究,但我首先希望看到使用UDP可以获得的最佳效果)

在下面的代码中,
txmax
是在已发送的最后100个数据包中发送单个UPD数据包(大小约1800字节)所花费的最大时间。我观察到:

  • txmax
    通常在6毫秒到20毫秒的范围内,这是正常的

  • 但是每分钟有一到两次,
    txmax
    峰值为250毫秒,即至少有一个
    sock。sendto(…)
    发送一个1.8 KB的UDP数据包需要250毫秒

问题:原因可能是什么?如何使用Python
socket
library减少UDP发送延迟?

注:

  • 我的家庭Wifi网络可能不是瓶颈,我只发送~100个数据包x 1.8 KB=180 KB/秒~1.4 Mbit/秒

  • 我已经尝试在
    REALTIME\u PRIORITY

    import psutil, os
    psutil.Process(os.getpid()).nice(psutil.REALTIME_PRIORITY_CLASS)
    
    但这并没有改变任何事情

  • 我已经尝试增加套接字的发送缓冲区大小:

    sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 16384)
    
    但影响很小

  • 如果我同时运行另一个进程,CPU达到峰值,那么这个问题就更明显了

  • sock.setblocking(False)
    似乎改变了这种情况:延迟现在为零,或者非常接近,但代码有时会完全停止,原因是:

    BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately
    

可复制示例:

import time, socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
txmax = 0
i = 0
while True:
    # data = getdatachunk()  # this is always stable and takes ~ 10ms with no exception 
                             # for reproducibility, replaced with:
    time.sleep(0.010)
    data = b'A' * 1800

    s = time.time()
    sock.sendto(data, ("192.168.1.17", 5006))  # send UDP packet
    txmax = max(txmax, time.time() - s)

    if i % 100 == 0:
        print(txmax)
        txmax = 0

    i += 1

经过广泛的测试,两件事大大改善了结果:

  • 设置超时:

    sock.settimeout(0.050)
    
    这样,就没有更多的问题了:
    txmax
    一直下降到1ms,250ms时不再有峰值

    我甚至从未经历过上述例外情况:

    socket.settimeout(值)
    设置阻止套接字操作的超时。value参数可以是表示秒的非负浮点数,也可以是None。如果给定了非零值,则如果超时时间值在操作完成之前已过,则后续套接字操作将引发超时异常。如果给定零,则将套接字置于非阻塞模式。如果未给出任何值,则将套接字置于阻塞模式

  • 至于录音部分(这里不谈这个话题),我终于注意到了

    import psutil, os; psutil.Process(os.getpid()).nice(psutil.REALTIME_PRIORITY_CLASS)
    
    彻底解决了音频爆裂的问题


感谢您的编辑!我很惊讶看到你大部分的传输都有延迟。在Linux系统上,默认套接字传输缓冲区远大于1800字节,例如,我的系统上的默认值为
212992
。我试着在我的系统上运行你的代码,我得到的大部分是
0.00015
即0.2ms(这仍然让我有点惊讶。
ping
以太网的往返时间是~0.4ms。我认为这个UDP传输应该只是得到缓冲,而不是等待,除非缓冲区填满)。300秒后,我看不到任何超过0.6毫秒的东西。感谢您运行这些测试@sourcejedi!也许在Windows上,
socket
的优先级较低?(我将在几秒钟内更新问题,使用“阻塞”与“不阻塞”测试)