当前位置:  开发笔记 > 编程语言 > 正文

使用非阻塞udp读取时缺少消息

如何解决《使用非阻塞udp读取时缺少消息》经验,为你挑选了2个好方法。

在两个主机之间的udp中使用非阻塞读取时,我遇到了丢失消息的问题.发件人在linux上,读者在winxp上.python中的这个例子显示了这个问题.
以下是用于显示问题的三个脚本.
send.py:

import socket, sys
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
host = sys.argv[1]
s.sendto('A'*10,   (host,8888))
s.sendto('B'*9000, (host,8888))
s.sendto('C'*9000, (host,8888))
s.sendto('D'*10,   (host,8888))
s.sendto('E'*9000, (host,8888))
s.sendto('F'*9000, (host,8888))
s.sendto('G'*10,   (host,8888))

read.py

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('',8888))
while True:
    data,address = s.recvfrom(10000)
    print "recv:", data[0],"times",len(data) 

read_nb.py

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(('',8888))
s.setblocking(0)
data =''
address = ''
while True:
    try:
        data,address = s.recvfrom(10000)
    except socket.error:
        pass
    else: 
        print "recv:", data[0],"times",len(data) 

示例1(工作正常):

ubuntu> python send.py
winxp> read.py

从read.py得到这个ok结果:

recv:A次10次
recv:B次9000次
recv:C次9000次
recv:D次10次
recv:E次9000次
recv:F次9000次
recv:G次10次

示例2(缺少消息):
在这种情况下,read_nb.py通常不会捕获短消息.我给出了它的两个示例.

ubuntu> python send.py
winxp> read_nb.py

从read_nb.py给出这个结果:

recv:A次10次
recv:B次9000次
recv:C次9000次
recv:D次10次
recv:E次9000次
recv:F次9000次

上面是缺少的最后10个字节的消息

下面是中间丢失的10字节消息

recv:A次10次
recv:B次9000
recv:C次9000
recv:E次9000
recv:F次9000
recv:G次10

我已经在windows上检查过wireshark,并且每次捕获所有消息时它们都会到达主机接口,但不会被read_nb.py捕获.解释是什么?

我也尝试过使用linux上的read_nb.py和windows上的send.py,然后就可以了.所以我认为这个问题与winsock2有关

或者我可能以错误的方式使用非阻塞udp?



1> Len Holgate..:

如果数据报到达主机(正如你的wireshark日志所示),那么我看到的第一个地方是套接字recv缓冲区的大小,尽可能大,并尽可能快地运行.

当然,这完全是UDP的预期.您应该假设数据报可以随时因任何原因丢弃.您也可以多次获得数据报...

如果您需要可靠性,那么您需要构建自己的,或使用TCP.



2> Nikolai Feti..:

使用UDP丢失消息是正常的 - 传输层不保证数据报的顺序或传递.如果您希望它们按顺序和/或始终交付,请自行切换到TCP或实施排序和/或确认/超时/重传.

对于您的示例 - 大消息大于普通以太网MTU 1500减去八个字节的UDP报头(除非您使用巨型帧),因此将由发送方分段.这会给发送器和接收器带来更多负载,但接收器上的负载更多,因为它需要将片段保留在内核内存中,直到完整的数据报到达为止.

我怀疑你是否溢出了36030字节的接收缓冲区,但后来我从不在Windows上进行网络连接,所以你最好检查SO_RECVBUF接收器上套接字选项的值,如@Len建议的那样.

还要检查输出netstat -s以查看丢弃的数据包计数.


windows:s.getsockopt(socket.SOL_SOCKET,socket.SO_RCVBUF)= 8192字节.ubuntu:buf = 112640字节
推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有