Python套接字和UDP:数据包队列如何帮助发送方比接收方更快

时间:2019-11-05 21:57:22

标签: python sockets udp

有一个接收器在循环并调用socket.recv

import socket
import time

UDP_IP = "127.0.0.1"
UDP_PORT = 5005

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # Internet  # UDP

sock.bind((UDP_IP, UDP_PORT))

sock.settimeout(0.001)

while True:
    try:
        data = sock.recv(1024)  # buffer size is 1024 bytes
    except socket.timeout:
        pass

    time.sleep(0.01)

发件人使用socket.sendto循环发送消息,并递增计数:

import socket

UDP_IP = "127.0.0.1"
UDP_PORT = 5005

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # Internet  # UDP

TOTAL_TO_SEND = 10000

messages = [str.encode(f"{num}") for num in range(TOTAL_TO_SEND)]

for total_sent in messages:
    sock.sendto(total_sent, (UDP_IP, UDP_PORT))

使用此设置,在发送方发送下一条消息之前,接收方的循环速度不足以回到recv行。

使用UDP允许丢失数据,我认为也许在接收者尚未回到recv时到达的消息将被跳过。但是事实并非如此。

当我仅发送10,000条消息(TOTAL_TO_SEND = 10000)时,即使发送几乎立即完成,接收方也需要花费一些时间来浏览所有10000条消息,但不会跳过任何一条。这意味着在接收者尚未准备好时,到达的消息会有一些缓冲/队列,它们会一直存储,直到接收者的代码能够处理所有消息为止。

但是,当我发送10倍的消息(TOTAL_TO_SEND = 100000)时,会有一个截止值(对于我的最新运行为15355),在该截止值以下将处理每条消息,此后它一次跳过数百条。在我看来,这意味着缓冲区/队列已满,然后循环仅足够快,不足以处理每发送几百条消息中的一条消息。

有限大小队列理论的更多证据是,增加消息大小(通过在每个消息前添加一些0)可以降低开始跳过消息的截止时间。每个邮件前面加上100 0将导致截止时间为641,而不是15355。

我无法找到关于此行为的详尽解释,所以想知道这里是否有人知道此“数据包队列”在Python套接字中的工作方式以及它的参数是什么。它的大小已知吗?可以增加吗?消息消失之前有时间限制吗?有相关文件吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

这不完全是“详尽的解释”,而是一些信息:

您可以使用getsockoptsetsockopt在Python中查看和设置套接字的参数。

在这种情况下,相关参数是接收缓冲区的大小,即socket.SO_RCVBUF

print(sock.getsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF))

给我看了65536

您可以使用

sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVBUF, 65536 * 100)

使其比原来大100倍。这样的结果是在开始跳过消息之前,缓冲区中存储的数据量是原来的100倍。

将其设置得太大可能不是一个好主意,但是我不知道,所以我会让其他人对此感到高兴。

相关问题