我正在让服务器使用 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/