Domanda

Ho problemi con i messaggi mancanti quando si utilizza lettura non bloccante in UDP tra due host. Il mittente è su Linux e il lettore è su WinXP. Questo esempio mostra in pitone il problema.
Qui ci sono tre script usati per mostrare il problema.
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) 

Esempio 1 (funziona bene):

Ubuntu> python send.py
WinXP> read.py

dare questo risultato ok da read.py:

recv: A volte 10
RECV: volte B 9000
RECV: C volte 9000
RECV: D volte 10
RECV: E volte 9000
RECV: F volte 9000
RECV: G volte 10

Esempio 2 ( messaggi mancanti ):
in questo caso i messaggi brevi non saranno spesso Catturato da read_nb.py Io do due esempi di come può sembrare.

Ubuntu> python send.py
WinXP> read_nb.py

dare questo risultato da read_nb.py:

recv: A volte 10
RECV: volte B 9000
RECV: C volte 9000
RECV: D volte 10
RECV: E volte 9000
RECV: F volte 9000

di cui sopra è l'ultimo messaggio 10 byte mancante

sotto è un messaggio 10 byte nel mezzo mancante

recv: A volte 10
RECV: volte B 9000
RECV: C volte 9000
RECV: E volte 9000
RECV: F volte 9000
RECV: G volte 10

Ho verificato con Wireshark su Windows e ogni volta tutti i messaggi viene catturato in modo che raggiungano l'interfaccia host, ma non viene catturato da read_nb.py. Qual è la spiegazione?

Inoltre ho provato con read_nb.py su Linux e send.py su Windows e quindi funziona. Così ho dato che questo problema ha a che fare con Winsock2

O forse sto usando non bloccante UDP nel modo sbagliato?

È stato utile?

Soluzione

Perdere messaggi è normale con UDP - il livello di trasporto non ordina garanzia o la consegna di datagrammi. Se li volete in ordine e / o sempre consegnato, passare a TCP o implementare la sequenza e / o ACK / timeout / ritrasmissione te stesso.

Per il tuo esempio - i messaggi di grandi dimensioni sono più grandi del normale Ethernet MTU di 1500 meno otto byte di intestazione UDP (a meno che non si sta utilizzando jumbo frame) e quindi saranno frammentati dal mittente. Questo mette più carico su mittente e ricevente, ma più sul ricevitore in quanto ha bisogno di mantenere i frammenti nella memoria del kernel fino a quando il datagramma completo arriva.

dubito che traboccano buffer di ricezione con 36030 byte, ma poi non lo faccio mai messa in rete su Windows, in modo da controllare meglio il valore di opzione presa SO_RECVBUF del sul ricevitore come suggerisce @Len.

Inoltre controllare l'uscita di netstat -s per vedere il sceso conta pacchetto.

Altri suggerimenti

Se i datagrammi sono sempre per l'host (come i tuoi programmi di log Wireshark) poi il primo posto mi piacerebbe guardare è la dimensione del buffer presa recv, renderlo il più grande possibile, e correre il più velocemente possibile .

Naturalmente questo è completamente previsto con UDP. Si deve presumere che i datagrammi possono essere gettati in qualsiasi momento e per qualsiasi motivo. Inoltre è possibile ottenere datagrammi più di una volta ...

Se avete bisogno di affidabilità, allora avete bisogno di costruire il proprio, o di utilizzare il protocollo TCP.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top