python - 有没有办法不缓冲来自 UDP 套接字的数据

标签 python sockets synchronization udp timing

我正在让服务器使用 UDP 将时钟滴答作为多播消息发送。服务器的代码是这样的:

import socket
import struct
import sys
import time

multicast_group = ('224.3.29.71', 10000)
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(0.2)
ttl = struct.pack('B', 255)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, ttl)

try:
    i = 0
    while True:
        #print "tick"

        sent = sock.sendto(str(i), multicast_group)
        i += 1
        time.sleep(1.0/25.0)

finally:
    print "closing socket"
    sock.close()

我希望客户端在收到蜱虫时执行某些操作,但跳过在处理时错过的蜱虫。

例如,如果客户端收到tick #1,但在处理时错过了tick #2 和tick #3,我希望tick #4 成为下一条收到的消息。

但是,由于套接字是缓冲的,因此它有时会收到应该跳过的滴答声。

这是客户端的代码:

import socket
import struct
import sys
import time

multicast_group = '224.3.29.71'
server_address = ('', 10000)

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(server_address)
sock.setblocking(0)

group = socket.inet_aton(multicast_group)
mreq = struct.pack('4sL', group, socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, mreq)

while True:
    try:
        data, address = sock.recvfrom(1024)
        print data
        time.sleep(1) #simulate processing
    except socket.error:
        pass

客户端输出: 1 2 3 4 5 ...

我应该做什么才能获得我想要的行为?

编辑:为了扩展问题,每次客户端收到蜱虫时我都会记录一个事件。我想记录以下序列:[触发,暂停,触发,暂停],但是,由于缓冲了一些滴答声,我得到:[触发,暂停,触发,触发,触发],使我的事件彼此接近时间。

最佳答案

套接字缓冲区位于内核内部,而不是 python 内部。每当有数据包进入时,它就会被放入该缓冲区中,直到用户空间从内核中读取它。您可以使用setsockopt 更改缓冲区的大小,但这是以字节为单位的大小,而不是以数据包为单位的大小。而且将其设置得太小并不是一个好主意,因为如果机器上接收到数据包并且套接字缓冲区已满,则新数据包将被丢弃。

更好的方法是保持套接字缓冲区不变,但将套接字设置为非阻塞,然后调用 recvfrom 直到不再获得数据 - 然后处理您读取的最后一个数据包。

关于python - 有没有办法不缓冲来自 UDP 套接字的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23896836/

相关文章:

python - 使用 str 中的常量值在 pandas df 中添加日期列

python - 将秒转换为分钟、小时和天的函数

Java服务器结构

qt - UDP 拆分/合并。哪一层处理它? (QT网络)

java - 在 Java EE 中限制对特定方法的多次访问的过程

java - 当多个 JVM 访问同一个数据库时,如何在 Java 中获取行级锁?

python - 为什么我不能在python中访问这个类成员?

python - 什么时候在 python 中收集对象垃圾?

c - 接收未知大小数据的最佳方法?

Java:跨多个服务器同步线程