UDP-Pakete, Gesehen von Wireshark, Gedroppt von (nicht einmal erreichen) WSARecvFrom

8

Ich habe ein ziemlich verwirrendes Problem.
Ich benutze eine große C ++ - Bibliothek für die Behandlung eines proprietären Protokolls über UDP unter Windows XP / 7. Während des Programmlaufs wird ein Port überwacht und auf Verbindungen von entfernten Peers gewartet.

Die meiste Zeit funktioniert das gut. Aufgrund einiger Probleme, habe ich beschlossen, einen einfachen Debug-Print direkt nach dem Aufruf von WSARecvFrom hinzuzufügen (die Win32-Funktion, die in der Bibliothek verwendet wird, um Datagramme von meinem interessanten Socket zu empfangen und zu sagen, welche IP-Adresse) und Port sie kamen aus).
Seltsamerweise habe ich in einigen Fällen entdeckt, dass Pakete auf der Ebene OS fallengelassen werden (dh ich sehe sie in Wireshark, sie haben den richtigen dst-Port, alle Prüfsummen sind korrekt - aber sie erscheinen nie in den Debug-Drucken, die ich in den Code implantiert habe).

Nun, ich bin voll von der Tatsache (Leute neigen dazu, ein bisschen zu oft zu erwähnen), dass "UDP nicht die Lieferung garantiert" - aber das ist nicht relevant, wie die Pakete sind erhalten an der Maschine - ich sehe sie in Wireshark.
Außerdem kenne ich OS-Puffer und das Potenzial, sich zu füllen, aber hier kommt der komische Teil ...

Ich habe einige Nachforschungen angestellt, um herauszufinden, welche Pakete genau fallengelassen werden. Was ich entdeckt habe, ist, dass alle verlorenen Pakete zwei Dinge gemeinsam haben (obwohl einige , aber definitiv nicht am meisten , der Pakete, die nicht sind gelöscht teilen diese auch):

  1. Sie sind klein. Viele der Pakete im Protokoll sind groß, nahe bei MTU - aber alle Pakete, die gelöscht werden, sind unter 100 Bytes (brutto).
  2. Sie sind immer einer von zweien: ein SYN-Äquivalent (dh das erste Paket, das ein Peer an uns sendet, um eine Kommunikation zu initiieren) oder ein FIN-Äquivalent (dh ein Paket, das ein Peer sendet, wenn er nicht mehr am Sprechen interessiert ist) zu uns).

Kann eine dieser beiden Eigenschaften die OS-Puffer beeinflussen und dazu führen, dass Pakete zufällig (oder sogar interessanter - selektiv) gelöscht werden?
Jedes Licht, das auf dieses seltsame Problem geworfen wird, wäre sehr willkommen.

Vielen Dank.

BEARBEITEN (24.10.12):

Ich glaube, ich habe ein wichtiges Detail übersehen. Es scheint, dass die Pakete, die vor der Ankunft gelöscht wurden, etwas anderes gemeinsam haben: Sie (und ich fange an zu glauben, nur sie) werden von "neuen" Peers, dh Peers, die es sind, an den Server gesendet strong> hat nicht versucht, vorher Kontakt aufzunehmen .

Wenn zum Beispiel ein syn-äquivalentes Paket von einem Peer * kommt, den wir noch nie zuvor gesehen haben, wird es von WSARecvFrom nicht gesehen. Wenn wir jedoch ein syn-äquivalentes Paket an diesen Peer selbst gesendet haben (auch wenn es zu diesem Zeitpunkt nicht geantwortet hat), sendet es jetzt uns ein Syn- Äquivalent, wir werden es sehen.

(*) Ich bin nicht sicher, ob dies ein Peer ist, den wir nicht gesehen haben (zB ip: port) oder nur einen Port , den wir nicht gesehen haben vorher.

Hilft das?
Ist das eine Art WinSock-Option, von der ich noch nie gehört habe? (Wie ich oben sagte, ist der Code nicht meiner, also kann es Socket-Optionen verwenden, die mir nicht bekannt sind)

Nochmals vielen Dank!

    
Oded R. 11.10.2012, 07:37
quelle

3 Antworten

3

Das Betriebssystem verfügt über einen Puffer fester Größe für Daten, die an Ihrem Socket angekommen sind, aber noch nicht von Ihnen gelesen wurden. Wenn dieser Puffer erschöpft ist, fängt er an, Daten zu verwerfen. Die Debug-Protokollierung kann dies verschlimmern, indem die Rate, mit der Daten aus dem Socket abgerufen werden, verzögert wird, was die Wahrscheinlichkeit von Überläufen erhöht.

Wenn dies das Problem ist, könnten Sie zumindest die Instanzen reduzieren, indem Sie einen größeren recv-Puffer anfordern.

Sie können die Größe des Recv-Puffers Ihres Sockets mit

überprüfen %Vor%

und Sie können es mit

vergrößern %Vor%

Wenn Sie sehen, dass Daten vom Betriebssystem empfangen werden, aber nicht an Ihren Socket-Client gesendet werden, könnten Sie verschiedene Protokollierungsansätze in Betracht ziehen. z.B.

  • Melden Sie sich bei einem RAM-Puffer an und drucken Sie ihn nur gelegentlich (in jeder Größe, die Sie als am effizientesten profilieren)
  • Melden Sie sich von einem Thread mit niedriger Priorität ab, indem Sie entweder akzeptieren, dass die Speicheranforderungen dafür nicht vorhersehbar sind, oder indem Sie Code hinzufügen, um Daten aus dem Puffer des Protokolls zu löschen, wenn dieser voll ist
simonc 11.10.2012 08:11
quelle
0

Deaktivieren Sie die Windows-Firewall.

Stimmt das? Wenn dies der Fall ist, können Sie die Firewall wahrscheinlich wieder aktivieren und einfach eine Regel für Ihr Programm hinzufügen.

Das ist meine logischste Annahme, basierend auf dem, was Sie hier in Ihrem Update gesagt haben:

  

Es scheint, dass die Pakete, die vor der Ankunft gelöscht wurden, etwas anderes teilen   gemeinsam: Sie (und ich fange an zu glauben, nur sie) werden geschickt   der Server von "neuen" Peers, d. h. Peers, mit denen er nicht in Kontakt gekommen ist   vorher.

    
selbie 17.08.2013 05:53
quelle
0

Bei redhat-linux gab es ein ähnliches Problem. Dies stellt sich als Routing-Problem heraus.

RCA ist wie folgt. 1. Richtig, dass UDP die Zielmaschine erreichen kann (gesehen auf Wireshark). 2. Jetzt wird die Route zur Quelle nicht gefunden, so dass keine Antwort auf dem Wireshark zu sehen ist. 3. Auf einigen Betriebssystemen können Sie das Anfragepaket auf dem Wireshark sehen, aber OS liefert nicht wirklich den Paketsocket (Sie können dieses Socket im netstat-nap sehen). 4. Überprüfen Sie in diesem Fall immer ping (ping -I)

Rgds, Kishor

    
Shiv Kishore Mishra 02.02.2015 08:58
quelle