2010-10-18 2 views
4

У меня проблема с отсутствующими сообщениями при использовании неблокирующего чтения в udp между двумя хостами. Отправитель находится на linux, и читатель находится на winxp. Этот пример в python показывает проблему.
Вот три сценария, используемые для показа проблемы.
send.py:Отсутствие сообщений при чтении с неблокирующим udp

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 (работает нормально):

убунту>Python send.py
WinXP>read.py

дать этот результат с ОК read.py:

Recv: а раз 10
RECV: раз B 9000
recv: C раз 9000
recv: D раз 10
recv: E раз 9000
recv: F раз 9000
ПРИЕМ: G раз 10

Пример 2 (отсутствуют сообщения):
в этом случае короткие сообщения не часто пойманные на read_nb.py я приведу два примера того, как это может выглядеть.

убунту>питон send.py
WinXP>read_nb.py

дают этот результат read_nb.ру:

RECV: А раз 10
RECV: раз C 9000
RECV:: раз B 9000
RECV D раз 10
Recv: E раз 9000
Recv: F раз 9000

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

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

повторно раз в 10
RECV:: резюме раз B 9000
RECV: C раз 9000
Recv: E раз 9000
RECV: F раз 9000
Recv: G раз 10

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

Я также попытался с read_nb.py на linux и send.py на окнах, а затем он работает. Итак, я полагаю, что эта проблема имеет какое-то отношение к winsock2

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

ответ

4

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

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

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

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

+1

windows: s.getsockopt (socket.SOL_SOCKET, socket.SO_RCVBUF) = 8192 байта. ubuntu: buf = 112640 bytes – lgwest

+0

ОК, вот и проблема. Хорошо знать. –

+1

Хм, так я предлагаю решение, и Николай принимает принятый ответ, нет справедливости :( –

6

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

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

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

+0

Вот +1 и справедливость для вас :) –

Смежные вопросы