有没有办法不缓存UDP套接字的数据
我正在做一个服务器,它通过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()
我希望客户端在收到一个滴答时能做点事情,但在处理过程中跳过它错过的滴答。
举个例子,如果客户端收到滴答#1,但在处理时错过了滴答#2和#3,我希望下一个收到的消息是滴答#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 ...
我该怎么做才能实现我想要的效果呢?
补充说明一下问题:每次客户端收到一个滴答时,我都会记录一个事件。我想记录的顺序是:[触发,暂停,触发,暂停],但由于一些滴答被缓冲,我得到的是:[触发,暂停,触发,触发,触发],这让我的事件时间间隔太近了。
1 个回答
3
套接字缓冲区是在操作系统的内核里面,而不是在Python里面。每当有数据包到达时,它会被放进这个缓冲区,直到用户空间从内核中读取它。你可以使用setsockopt来改变缓冲区的大小,但这个大小是以字节为单位,而不是以数据包为单位。如果把缓冲区设置得太小,就不太好,因为如果机器上收到一个数据包,而套接字缓冲区已经满了,新到的数据包就会被丢弃。
更好的方法是保持套接字缓冲区的默认设置,但把套接字设置为非阻塞模式,然后不断调用recvfrom,直到没有更多数据为止——然后处理你最后读取的数据包。