| Autor |
Beitrag |
Knulli
      
Beiträge: 116
Erhaltene Danke: 2
Win2k, Win7, Win10
D5, D2005, D2006, D2007, D10.4.2
|
Verfasst: Mi 15.11.06 14:14
Moin,
Beim UDPSockUtil knallts ab und an in der zweiten Assert-Anweisung (Rückgabewert). Hab ich erstmal so eingebaut, weil ich sehen wollte, obs wirklich passiert. Es passiert gelegentlich.
Delphi-Quelltext 1: 2: 3: 4:
| Assert(BytesToSend <= USU_MAX_DGRM_SIZE); BytesSend := m_UdpSock.SendBuf(aCommand, BytesToSend); Assert(BytesToSend = BytesSend); |
Was ist das beste, wenn BytesSend <> BytesToSend ist, solange wiederholen, bis es klappt? Wie lange Pause zwischen den Versuchen? Muß ich "Application.ProcessMessages" oder sowas ähnlichen zwischendurch aufrufen?
Jemand schonmal das gleiche Problem gehabt und vernünftig gelöst? Was sind sinnvolle Timeouts?
Knulli
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 15.11.06 14:38
Moin!
Sendest du Broadcasts? Setz mal .CloseInactiveSockets := TRUE; und probier´s dann nochmal. Tritt der Fall dann immer noch auf?
Allgemein: WARUM nicht alle übergebenen Bytes gesendet wurden, ist ja nun eigentlich die interessante Frage. Hab leider so auf dem Stehgreif auch keine Antwort drauf. Allerdings macht der UdpSockUtil an dieser Stelle nix anderes, als den WSA-Returncode weiterzureichen. So gesehen wäre mal in der WSA-Doku zu stöbern, welche Gründe ein UDP-Socket haben könnte, nicht alle Daten gesendet zu haben. Haste da schonmal nachgesehen?
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
Knulli 
      
Beiträge: 116
Erhaltene Danke: 2
Win2k, Win7, Win10
D5, D2005, D2006, D2007, D10.4.2
|
Verfasst: Mi 15.11.06 15:41
CloseInactiveSockets habe ich auf false gelassen, weil ich irgenwie im Hinterstübchen hatte, daß dann jedesmal nach dem Senden eines Paketes wieder der Socket freigegeben wird. Das klingt performancemäßig nicht so gut. Kann man nicht im Bedarfsfall (also z.B. wenn BytesSend = 0 zürückkommt) so ne Art GarbageCollector anschubsen? Habs aber gerade auch noch mal ausprobiert, CloseInactiveSockets immer auf true stehen zu lassen, es passiert trotzdem.
Interessanter und vielleicht sehr wichtiger Punkt ist, daß wenn es nicht klappt, gar nichts gesendet wurde (BytesSend=0). Zumindest bei mir auf meinen Rechnern. Gibts da auch andere Beobachtungen?
Ich will aber ehrlich gesagt auch lieber erstmal gar nicht darüber nachdenken, was ist, wenn von den zu sendenden Daten nur die Hälfte gesendet wird. Da UDP die Reihenfolge nicht einhält, kommt da sicherlich kompletter Blödsinn bei raus, wenn man dann in einer while-Schleife solange sendet, bis das Paket komplett raus ist. Das Paket, was ich hier verschicken will ist außerdem schon die kleinste Einheit einer Sequenz aus Paketen. Also müßte eine Wiederholung des kompletten Paketes doch das Beste sein, oder? Nur wie lange sollte man mindestens warten?
Broadcasts kommen zwischendurch auch vor. Ich habe einen Timer, der alls 5 Sekunden einen Broadcast mit in den Sendepuffer packt, um den anderen Rechnern im Verbund ein Lebenszeichen zu geben. Die Senderoutine schaltet dann immer um.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| procedure TPartnerPC.SendCommand(var aCommand: TNetPaket); var n: Integer; BytesToSend, BytesSend: Integer; begin m_UdpSock.Broadcast := (IP_Addr = cBroadCastAddress) OR (Length(IP_Addr) = 0); if Not m_UdpSock.Broadcast then m_UdpSock.RemoteHost := IP_Addr; for n := 1 to cLenDSKennung do aCommand.Kennung[n] := cDSKennung[n]; BytesToSend := aCommand.NetID.Size + SizeOf(TNetID) + cLenDSKennung;
Assert(BytesToSend <= USU_MAX_DGRM_SIZE); BytesSend := m_UdpSock.SendBuf(aCommand, BytesToSend); if BytesToSend <> BytesSend then Network.frmNetwork.Caption := Format('BytesToSend: %d, BytesSend: %d', [BytesToSend, BytesSend]); end; |
Ich bin am Überlegen, ob ich den Rückgabewert einfach ignoriere. Eine Kontrolle, ob ich eine Antwort auf das Paket bekommen habe, gibt es ja auch noch und die wiederholt das Paket dann (idR. eine Sekunde später) sowieso noch ein paar mal, bis ein richtiger Timeout zuschlägt. War halt nur die Frage, ob man mit dem Rückgabewert irgendetwas anfangen sollte.
Die WSA Doku schweigt sich übrigens aus, WARUM es sein kann, daß weniger gesendet werden, als gewollt. Ich hätte da WSAGetLastError aufrufen, um mehr rauszubekommen, aber das machst Du ja schon im Control. Warum wird eigentlich "WSAEWOULDBLOCK" dabei rausgefiltert?
Noch ne ganz andere Frage:
Sollte ich meine Daten noch mit einer CRC absichern? Kann es mir passieren, daß ein Paket beim Sender (UdpSock.SendBuf)ordnungsgemäß raus geht und beim Empfänger (UdpSock.ReceiveBuf) zerstümmelt ankommt?
Knulli
|
|
Narses
      

Beiträge: 10185
Erhaltene Danke: 1261
W11x64
TP3 .. D7pro .. D10.2CE
|
Verfasst: Mi 15.11.06 20:34
Moin!
Knulli hat folgendes geschrieben: | | CloseInactiveSockets habe ich auf false gelassen, weil ich irgenwie im Hinterstübchen hatte, daß dann jedesmal nach dem Senden eines Paketes wieder der Socket freigegeben wird. |
So ist es.
Knulli hat folgendes geschrieben: | | Das klingt performancemäßig nicht so gut. |
Das dürfte relativ egal sein; kann mir nicht vorstellen, dass die Netzwerklatenz kleiner als die interne Verarbeitungsgeschwindigkeit ist.
Knulli hat folgendes geschrieben: | | Kann man nicht im Bedarfsfall (also z.B. wenn BytesSend = 0 zürückkommt) so ne Art GarbageCollector anschubsen? |
Kannst du doch in deinem Code tun: eine if-Abfrage hinter den .SendBuf und dann einmal mit .CloseInactiveSockets klappern.
Knulli hat folgendes geschrieben: | | Habs aber gerade auch noch mal ausprobiert, CloseInactiveSockets immer auf true stehen zu lassen, es passiert trotzdem. |
OK, war auch nur eine spontane Idee, weil ich da mal was in dieser Richtung gehört hatte (ich hatte auch keine Änderung erwartet).
Knulli hat folgendes geschrieben: | | Interessanter und vielleicht sehr wichtiger Punkt ist, daß wenn es nicht klappt, gar nichts gesendet wurde (BytesSend=0). Zumindest bei mir auf meinen Rechnern. Gibts da auch andere Beobachtungen? |
Nein, habe nichtmal diesen Fall bisher "gesehen".
Knulli hat folgendes geschrieben: | | Da UDP die Reihenfolge nicht einhält, kommt da sicherlich kompletter Blödsinn bei raus, wenn man dann in einer while-Schleife solange sendet, bis das Paket komplett raus ist. Das Paket, was ich hier verschicken will ist außerdem schon die kleinste Einheit einer Sequenz aus Paketen. |
Wenn es von entscheidender Bedeutung ist, dass die Daten korrekt eintreffen, warum dann nicht TCP?
Knulli hat folgendes geschrieben: | | Also müßte eine Wiederholung des kompletten Paketes doch das Beste sein, oder? Nur wie lange sollte man mindestens warten? |
Ja, ich würde auch immer das ganze Paket senden und im Empfänger Fragmente verwerfen (wobei das schon interessant wäre, AFAIK kennt UDP kein Fragmenting!). Schick dir eine Fensternachricht, dass du nochmal senden sollst, das sollte langen.
Knulli hat folgendes geschrieben: | | Eine Kontrolle, ob ich eine Antwort auf das Paket bekommen habe, gibt es ja auch noch und die wiederholt das Paket dann (idR. eine Sekunde später) sowieso noch ein paar mal, bis ein richtiger Timeout zuschlägt. |
Nochmal: warum dann nicht TCP?
Knulli hat folgendes geschrieben: | Ich bin am Überlegen, ob ich den Rückgabewert einfach ignoriere.
[...]
War halt nur die Frage, ob man mit dem Rückgabewert irgendetwas anfangen sollte. |
Im Zweifel halt loggen und beobachten; vielleicht lässt sich ja eine Gemeinsamkeit in den Situationen finden, in denen der Socket nix senden will.
Knulli hat folgendes geschrieben: | | Warum wird eigentlich "WSAEWOULDBLOCK" dabei rausgefiltert? |
Weil es (im Kontext von asynchronen Sockets) kein Fehler ist, sondern "nur" eine Benachrichtigung. In diesem Fall sollte man dann halt später nochmal probieren (hm, mir fällt gerade auf, dass genau das eine Situation sein könnte, die diesen Effekt symptomatisch bewirken könnte - allerdings sollte dieser Returncode bei UDP eigentlich gar nicht auftreten (hab ich nur zur Sicherheit drin)).
Knulli hat folgendes geschrieben: | | Sollte ich meine Daten noch mit einer CRC absichern? Kann es mir passieren, daß ein Paket beim Sender (UdpSock.SendBuf)ordnungsgemäß raus geht und beim Empfänger (UdpSock.ReceiveBuf) zerstümmelt ankommt? |
Ich kenne kein Fragmenting bei UDP, wie gesagt. Deshalb würde ich davon ausgehen, dass entweder das Paket vollständig ankommt, oder eben nicht; aber nicht "teilweise".
Unabhängig davon ist es aber keine schlechte Idee, eine Checksumme drin zu haben, oder zumindest einen Längenzähler als Verifikation für die Vollständigkeit.
cu
Narses
_________________ There are 10 types of people - those who understand binary and those who don´t.
|
|
|