Entwickler-Ecke
Internet / Netzwerk - Windows säumt Message?
freedy - Di 05.09.06 15:20
Titel: Windows säumt Message?
Hi!
Ich benutze die Komponente UDPSockUtil von Narses (hier im Forum). Alle 500msec treffen hier 20 Pakete à ca. 1000 Bytes an. Ist ja eigentlich nicht viel. Trotzdem versäumt Windows die entsprechende Message in der Komponente auszulösen. Ethereal findet alle Pakete. Wie kann ich das optimieren? Hat jemand eine Idee?
Narses - Di 05.09.06 16:21
Moin!
Entscheidend ist der zeitliche Abstand der einzelnen Pakete zueinander, nicht die Menge oder Durchnittsdatenrate. ;) Ich hoffe aber doch, dass keine Daten verloren gehen, sondern du nur mehr als ein Paket pro Event erhältst - womit deine Anwendung durchaus rechnen muss! Die asynchronen Ereignisse sind kein adequates Mittel zur Signalisierung, auch nicht bei UDP! Siehe
FAQ-Beitrag [
http://www.delphi-library.de/topic_Datenpakete+bei+den+SocketKomponenten+auseinanderhalten_56194.html]. Anders ausgedrückt, garantiert dir die WSA nicht ein Ereignis pro Datenpaket, sondern nur, dass Daten eingetroffen sind! :shock:
Wenn du es exakt haben willst, mußt du einen Thread nehmen und mit blocking-socket-calls arbeiten. :D
cu
Narses
freedy - Mi 20.09.06 13:40
Hi Narses!
Hättest du dazu mal ein bisschen Code. Ich habe null Vorstellung davon wie ich das realisieren soll. Auch gerade weil mir blocking-socket-calls nichts sagen. Ich werde aber nach googlen.
Ich habe nochmal alles überprüft und eine Abfrage-Routine eingebaut, indem ich einfach die Paketnummern, die bei uns dranhängen, auswerte. Es fehlen definitiv Pakete, teilweise bis zu acht. Aber eben auch nicht immer. Die Umstände konnte ich bisher nicht ausmachen.
Narses - Mi 20.09.06 14:22
Moin!
freedy hat folgendes geschrieben: |
| Hättest du dazu mal ein bisschen Code. |
Nein, habe nix zur Hand, was ich rausgeben könnte. :(
freedy hat folgendes geschrieben: |
| Ich habe null Vorstellung davon wie ich das realisieren soll. Auch gerade weil mir blocking-socket-calls nichts sagen. |
Mein UdpSockUtil kann´s auch nicht. Müßtest das also eh komplett selbst aufsetzen. ;) Konkret bedeutet das, dass die WSA-Calls nicht direkt zurückkommen und dann später ein Ereignis auslösen, sondern die Calls sind erst dann beendet, wenn die WSA die Aufgabe auch tatsächlich durchgeführt hat.
freedy hat folgendes geschrieben: |
| Ich habe nochmal alles überprüft und eine Abfrage-Routine eingebaut, indem ich einfach die Paketnummern, die bei uns dranhängen, auswerte. Es fehlen definitiv Pakete, teilweise bis zu acht. Aber eben auch nicht immer. Die Umstände konnte ich bisher nicht ausmachen. |
Nochmal: Der auf der gleichen Maschine wie deine Anwendung laufende Sniffer sieht alle(!) Pakete, aber in der Anwendung fehlen Pakete? Ganz sicher?! :shock:
cu
Narses
freedy - Mi 20.09.06 14:39
| Zitat: |
| Nochmal: Der auf der gleichen Maschine wie deine Anwendung laufende Sniffer sieht alle(!) Pakete, aber in der Anwendung fehlen Pakete? Ganz sicher?! :shock: |
jupp, ganz sicher... das ist ja mein Problem.
Eine WSA-Komponente selbst aufsetzen schaffe ich zur Zeit nicht; glaube auch, dass mich das etwas überfordert. Netzwerke waren nie meine Spezialität, wie man hier merkt.
Deine Komponente arbeitet doch im Blocking-Modus, richtig? Deshalb verstehe ich nicht, warum einige Pakete verschluckt werden. Es könnte natürlich sein, da an meinem Ereignis, das nach dem Eintreffen ausgelöst wird, einiges dranhängt und doch etwas Rechenzeit vergeht, mehr Pakete ankommen, als verarbeitet werden können. Ich werde das mal ausprobieren...
freedy - Mi 20.09.06 15:08
So, bin wieder einen Schritt weiter... vielleicht finde ich auch gleich den Fehler.
Ich glaube inzwischen nicht mehr, dass er Pakete verliert. Wenn ich die Größe des Speichers abrufe, stehen da total falsche Werte drin. Unsere Pakete sind maximal 1048 Bytes an Daten lang. Das sollte mit UDP ja möglich und nicht das Problem sein.
Teilweise steht dann aber irgendwas um die 5000, 6000 oder auch 8000 drin... genau weiß ich's gerade nicht.
Auf jeden Fall stimmt das nicht. Wahrscheinlich hängen daran auch andere Fehler, die bei mir ausgelöst werden.
Teilweise, nicht immer, stehen dann im gesamten Puffer, wenn ich das richtig gesehen habe, zwei oder drei meiner Pakete, die dann aber nicht erkannt und nicht verarbeitet werden (mein Programm ahnt davon ja nichts).
Die Funktion ReceiveLength() sollte doch aber nur das zurückgeben, was auch angekommen ist, oder?
Narses - Mi 20.09.06 15:25
Moin!
freedy hat folgendes geschrieben: |
| Deine Komponente arbeitet doch im Blocking-Modus, richtig? |
Nein, meine Kompo arbeitet non-blocking (was man eben daran erkennt, dass WSA-Nachrichten verarbeitet werden). ;)
freedy hat folgendes geschrieben: |
| Unsere Pakete sind maximal 1048 Bytes an Daten lang. Das sollte mit UDP ja möglich und nicht das Problem sein. |
Hm, bei UDP gibt es max. Paketgrößen und in meiner Kompo die Konstante USU_MAX_DGRM_SIZE = 512 (Bytes). Ich hab das jetzt nicht mehr so sauber aus dem Gedächtnis drauf, wie da die Zusammenhänge im Detail waren, aber in meiner Kompo-Anleitung gebe ich vor, dass die Pakete nicht größer als die Konstante sein dürfen. :? :| Du hast doch in deiner Delphi-Version die MS-WSA-Hilfedateien, da steht es genau drin, müsste ich nachher mal schauen, ob ich da was finde... :gruebel:
freedy hat folgendes geschrieben: |
| Die Funktion ReceiveLength() sollte doch aber nur das zurückgeben, was auch angekommen ist, oder? |
Schau in den Quelltext ;), ReceiveLength holt die Angabe über IOCtlSocket, was die zu diesem Zeitpunkt im WSA-Buffer liegende Datenmenge liefert - kann aber zwischenzeitlich mehr werden, wenn du "lange genug" wartest, bis du die Daten holst. ;)
cu
Narses
freedy - Fr 22.09.06 13:53
Narses hat folgendes geschrieben: |
freedy hat folgendes geschrieben: | | Unsere Pakete sind maximal 1048 Bytes an Daten lang. Das sollte mit UDP ja möglich und nicht das Problem sein. |
Hm, bei UDP gibt es max. Paketgrößen und in meiner Kompo die Konstante USU_MAX_DGRM_SIZE = 512 (Bytes). Ich hab das jetzt nicht mehr so sauber aus dem Gedächtnis drauf, wie da die Zusammenhänge im Detail waren, aber in meiner Kompo-Anleitung gebe ich vor, dass die Pakete nicht größer als die Konstante sein dürfen. :? :| Du hast doch in deiner Delphi-Version die MS-WSA-Hilfedateien, da steht es genau drin, müsste ich nachher mal schauen, ob ich da was finde... :gruebel: |
Die Größe der Pakete scheint nicht so von Bedeutung zu sein. Jedenfalls kommen auch unsere Pakte mit 1024 oder auch wenig mehr durch. Soweit ich gesehen habe verträgt Windows 2003 Server nur 1500 Byte, XP und 2000 aber 2000 Bytes (inklusive Header).
Narses hat folgendes geschrieben: |
freedy hat folgendes geschrieben: | | Die Funktion ReceiveLength() sollte doch aber nur das zurückgeben, was auch angekommen ist, oder? |
Schau in den Quelltext ;), ReceiveLength holt die Angabe über IOCtlSocket, was die zu diesem Zeitpunkt im WSA-Buffer liegende Datenmenge liefert - kann aber zwischenzeitlich mehr werden, wenn du "lange genug" wartest, bis du die Daten holst. ;) |
Die Datenmengen variieren stark. Ich habe mal nur die Größe des Puffers ausgegeben. Irre. Liegt immer so um 8kB. Der Inhalt ist aber nur der unseres Paketes mit 1024 Bytes. Der Rest sind Nullen.
Ich bräuchte wirklich für jedes eintreffende Paket ein Ereignis, das sofort die Daten vielleicht einfach nur in den Speicher wegschreibt. Dann kann ich sie später verarbeiten. Ist das mit Windows überhaupt möglich? Hm... Gibt es evtl. auch eine Funktion, die mir anzeigt, wieviele Pakete gerade im Netzwerkstack warten?
Ich weiß ja nicht, ob das der Sinn deiner Komponente ist, aber wäre es möglich, diese zu erweitern. Bin ja auch gerne bereit, dich da zu unterstützen. :roll:
Narses - Fr 22.09.06 14:26
Moin!
freedy hat folgendes geschrieben: |
| Die Größe der Pakete scheint nicht so von Bedeutung zu sein. Jedenfalls kommen auch unsere Pakte mit 1024 oder auch wenig mehr durch. Soweit ich gesehen habe verträgt Windows 2003 Server nur 1500 Byte, XP und 2000 aber 2000 Bytes (inklusive Header). |
Mag mich täuschen, aber aus der Erinnerung darf das keinesfalls mehr als MTU werden, da UDP kein fragmenting kennt.
freedy hat folgendes geschrieben: |
| Die Datenmengen variieren stark. Ich habe mal nur die Größe des Puffers ausgegeben. Irre. Liegt immer so um 8kB. Der Inhalt ist aber nur der unseres Paketes mit 1024 Bytes. Der Rest sind Nullen. |
Kannst du mal genauer beschreiben, was du da gemacht hast? :gruebel: ;)
freedy hat folgendes geschrieben: |
| Ich bräuchte wirklich für jedes eintreffende Paket ein Ereignis, |
Dafür ist das Windows-Ereignissystem einfach nicht geschaffen - und auch gar nicht konzipiert (weil zu langsam). Der für die Ereignisauslösung verantwortliche Befehl ist ein WSAAsyncSelect, aber der liefert eben nur die Info, es sind Daten eingetroffen, nur nicht wie viele!
freedy hat folgendes geschrieben: |
| das sofort die Daten vielleicht einfach nur in den Speicher wegschreibt. Dann kann ich sie später verarbeiten. Ist das mit Windows überhaupt möglich? Hm... |
Das geht mit einem Listener-Thread und dem synchronen WSASelect.
freedy hat folgendes geschrieben: |
| Gibt es evtl. auch eine Funktion, die mir anzeigt, wieviele Pakete gerade im Netzwerkstack warten? |
Nicht wieviele Pakete, nur die Datenmenge in Bytes, AFAIK.
freedy hat folgendes geschrieben: |
| Ich weiß ja nicht, ob das der Sinn deiner Komponente ist, aber wäre es möglich, diese zu erweitern. Bin ja auch gerne bereit, dich da zu unterstützen. :roll: |
Danke für das Angebot, aber wie aus dem Text oben klar wird, ist das Ereignissystem von Windows dazu sowieso nicht in der Lage, das auf Paketebene runterzubrechen. Fazit: man kann die Kompo (weil ereignisorientiert) nicht dahingehend erweitern. :(
Daraus folgt wiederum: wenn du wirklich darauf ANGEWIESEN bist (was ich nicht glaube, das sollte mit einem entsprechend darauf ausgelegten Konzept auch mit der Information "Daten eingetroffen, unbekannt wieviele" möglich sein), einzelne Pakete ereignisorientiert zu verarbeiten, dann wirst du dazu eine eigene Kompo schreiben müssen, die das threadbasiert macht.
Leider kann ich dir dabei aber nicht behilflich sein, da ich zur Zeit mit anderen Projekten ausgelastet bin. :|
cu
Narses
freedy - Mo 25.09.06 16:09
Juchu, es läuft... wir konnten einige Probleme in unserer Kommunikation lösen. Inzwischen schicken wir die Paketgröße einfach mit, so dass wir nun keine Speicherzugriffsfehler mehr haben. Dadurch, dass wir mit "Move" den Speicher weiterverarbeiten, hat er uns, weil ja immer länger als erwartet, voll in andere Bereiche reingeschrieben.
Wir kommen so erstmal klar. Manchmal ist zwar der Netzwerkstack voll, so dass Pakete fehlen, aber das kriegen wir vielleicht auch noch hin.
Knulli - Fr 03.11.06 14:09
@freedy:
Kann es sein, daß Du beim Aufruf von "UdpSock.ReceiveBuf" den Rückgabewert nicht ausgewertet hast? Das was Du da so schreibst kommt mir alles sehr bekannt vor, weil es mir ähnlich erging.
Ich dachte auch erst, mit "UdpSock.ReceiveLength" bekomme ich die Anzahl Bytes, die bei einem nachfolgendem "UdpSock.ReceiveBuf" zurückgegeben werden. Dem ist aber NICHT so. Damit bekommst Du nur die Anzahl Bytes im Puffer, aber die tatsächlich vom nachfolgenden "UdpSock.ReceiveBuf" gelieferten Bytes sind idR. weniger.
Wenn Du mir der Übermittlung einer Paketlänge das Problem umgangen bist, ist die Auswertung des Returncodes doch eigentlich der bessere Weg. Die Längenangabe kannst Du ja anschließend immer noch auswerten.
Ich mache es sinngemäß so:
Delphi-Quelltext
1: 2: 3:
| RecvLen := m_UdpSock.ReceiveLength; SetLength(RecvBuffer, RecvLen); RecvLen := m_UdpSock.ReceiveBuf(PChar(RecvBuffer)^, RecvLen, Absender); SetLength(RecvBuffer, RecvLen); |
@narses:
Ich habe auch festgestellt, daß mit USU_MAX_DGRM_SIZE = 512 Byte nicht das Ende der Fahnenstange erreicht ist, zumal bei 512 zu sendenden Bytes tatsächlich ca. 50 Bytes mehr gesendet werden. Ich bin bis ca. 1500 Byte gekommen. Woher hast Du eigentlich die Angabe 512?
Knulli
Narses - Fr 03.11.06 14:35
Moin!
Knulli hat folgendes geschrieben: |
| Ich habe auch festgestellt, daß mit USU_MAX_DGRM_SIZE = 512 Byte nicht das Ende der Fahnenstange erreicht ist, zumal bei 512 zu sendenden Bytes tatsächlich ca. 50 Bytes mehr gesendet werden. Ich bin bis ca. 1500 Byte gekommen. |
Ja, das ist nicht sehr verwunderlich, tatsächliches Maximum ist MTU, aber der Wert ist ja sogar verbindungsabhängig. :shock: Deshalb geht es um einen Wert, der möglichst immer übertragen werden kann, weil UDP kein Fragmenting kennt. ;)
Knulli hat folgendes geschrieben: |
| Woher hast Du eigentlich die Angabe 512? |
Soweit ich mich erinnern kann, stand das in einem Nebensatz im MS-WinSock2-Helpfile. :gruebel: Weiß ich ehrlichgesagt aber auch nicht mehr soo genau, ist ja schon was her... ;)
cu
Narses
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2026 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!