пропущенные сообщения при чтении с неблокирующим udp - PullRequest
5 голосов
/ 18 октября 2010

У меня проблема с отсутствующими сообщениями при использовании неблокирующего чтения в 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:

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 тimes 9000

выше - последнее 10-байтовое сообщение отсутствует

ниже - 10-байтовое сообщение в середине отсутствует

recv: A times 10
recv: B times9000
recv: C времена 9000
recv: E времена 9000
recv: F времена 9000
recv: G времена 10

Я проверил Wireshark на окнах и каждый раз всесообщения перехватываются так, что они достигают интерфейса хоста, но не перехватываются read_nb.py.Какое объяснение?

Я также попытался с read_nb.py на Linux и send.py на Windows, и тогда это работает.Таким образом, я полагаю, что эта проблема как-то связана с winsock2

Или, может быть, я использую неблокирующий udp неправильно?

Ответы [ 2 ]

7 голосов
/ 18 октября 2010

Если дейтаграммы попадают на хост (как показывает ваш журнал wireshark), то первое, что я посмотрю, это размер буфера recv сокета, сделайте его настолько большим, насколько сможете, и работайте так быстро, как можете .

Конечно, это вполне ожидаемо с UDP. Вы должны предположить, что дейтаграммы могут быть выброшены в любой момент и по любой причине. Также вы можете получать дейтаграммы более одного раза ...

Если вам нужна надежность, вам нужно создать свой собственный или использовать TCP.

5 голосов
/ 19 октября 2010

Потеря сообщений - это нормально с UDP - транспортный уровень не гарантирует порядок или доставку дейтаграмм.Если вы хотите, чтобы они были в порядке и / или всегда доставлялись, переключитесь на TCP или внедрите последовательность и / или ack / timeout / retransmission самостоятельно.

К вашему примеру - большие сообщения больше обычного Ethernet MTU 1500 минусвосемь байтов заголовка UDP (если вы не используете гигантские кадры) и, таким образом, будут фрагментированы отправителем.Это увеличивает нагрузку как на отправителя, так и на получателя, но больше на получателя, поскольку ему нужно хранить фрагменты в памяти ядра до тех пор, пока не будет получена полная датаграмма.

Я сомневаюсь, что вы переполняете буфер приема 36030 байтами, но потомЯ никогда не работаю в сети в Windows, поэтому вам лучше проверить значение опции сокета SO_RECVBUF на приемнике, как подсказывает @Len.

Также проверьте вывод netstat -s, чтобы увидетьколичество пропущенных пакетов.

...