![]() |
Schnellere Kommunikation mit einer Fritzbox
Hallo in die Runde :),
diesmal hatte ich wirklich Schwierigkeiten bei der Wahl eines passenden Thementitels. Insofern sorry, falls der nicht ganz passend, vielleicht gar irreführend sein sollte. Erneut setze ich auf eure Hilfe und euren Sachverstand, weil ich mal wieder ein Problem habe. Aufgrund der Umstellung klassischer Telefonanschlüsse auf IP (NGN) und den damit verbundenen Änderungen arbeite ich derzeit an einer Möglichkeit, bestimmte Daten einer Fritzbox auszulesen und zum Teil grafisch darzustellen (konkret den Traffic-Graphen). Also hab ich geschaut, welche Möglichkeiten ich in dem Bereich mit Delphi habe, und bin dabei auf die ![]() Leider stellte ich fest, dass der Abruf der Informationen von der Fritzbox ziemlich lange dauert. Nach genauerer Untersuchung des Codes fiel mir der Aufruf von
Delphi-Quellcode:
vor Empfang der Informationen mit
Sleep(KEEP_ALIVE);
Delphi-Quellcode:
auf:
WinSock.recv(...);
[ADD]
Delphi-Quellcode:
[/ADD] Testhalber habe ich die KEEP_ALIVE Konstante reduziert von 300 auf 100, was leider zur Folge hat, dass der Abruf zwar schneller geht, aber teilweise(?) keine Informationen mehr zurückkommen. In einem anderen Test habe ich den Code analog zu dem
while (Result < 0) or (Result = cBufSize) do begin
Sleep(KEEP_ALIVE); FillChar(LBuffer, cBufSize, #0); Result := WinSock.recv(FSocket, LBuffer, cBufSize, 0); { * Die gelesenen Bytes übernehmen und die Anzahl aktualisieren. } FBufferStr := FBufferStr + LBuffer; Inc(FBytesRcvd, Result); end; ![]()
Delphi-Quellcode:
Folge: Code bleibt beim zweiten Aufruf der WinSock.recv-Funktion hängen.
repeat
Sleep(10); FillChar(LBuffer, cBufSize, #0); Result:= WinSock.recv(FSocket, LBuffer, cBufSize, 0); FBufferStr:= FBufferStr + LBuffer; Inc(FBytesRcvd, Result); until Result <= 0; Da ich mich so gar nicht in der Thematik Netzwerk-Programmierung, Sockets und dem Drumherum auskenne, die Fragen an euch:
Grüße Dalai |
AW: Schnellere Kommunikation mit einer Fritzbox
Diese Schleife Endet, wenn sie nichts empfing.
Also wenn die Übertragung beendet ist, wenn der Sender noch nichts liefern konnte (die angeforderten Daten noch zusammensucht) oder wenn er langsamer sendet, als den nächsten Lesedurchgang machst. Erstmal könnte man sofort lesen und bei einem bekannten/erkannten "Ende" sofort aufhören und ansonsten die Schleife nicht sofort bei "nichts gelesen" beenden, sondern DORT das "Sleep" integrieren, also nicht
Delphi-Quellcode:
sondern
(ReadCount = 0)
Delphi-Quellcode:
.
(ReadCount = 0) and (LetzteZeitWoCountGrößer0 > xxxMilliekunden)
|
AW: Schnellere Kommunikation mit einer Fritzbox
Was spricht gegen Indy oder Synapse für die Socket-Kommunikation zu verwenden? Damit würden einige Problemquellen wegfallen.
|
AW: Schnellere Kommunikation mit einer Fritzbox
Ich hab mal im OP den ursprünglichen Code von Garfield ergänzt, denn letztlich geht's um den und nicht um meine Modifikation zu Testzwecken.
Zitat:
Delphi-Quellcode:
-Schleife beziehst: Ja, richtig. Die Schleife endet aber auch, wenn der Socket geschlossen wurde. Vermutlich wird er das nicht, weil vorher setsockopt gerufen wird und dort ein keep-alive gesetzt wird.
repeat
Zitat:
Zitat:
Grüße Dalai |
AW: Schnellere Kommunikation mit einer Fritzbox
Zitat:
![]() Ich weiß nicht, wozu das Sleep gut sein soll. Standardmäßig blockieren die Socket-Funktionen sowieso schon solange, bis Daten empfangen wurden. Außer sie wurden mit SetSockOpt in den nonblocking-Modus versetzt. Aber in dem Fall wäre das hier eine sehr instabile Frickelei. |
AW: Schnellere Kommunikation mit einer Fritzbox
Zitat:
Delphi-Quellcode:
-Schleife auf Basis des MS-Beispiels. Problem dabei: der zweite Schleifendurchlauf bleibt bei Aufruf der recv-Funktion stehen, d.h. die Verbindung wird eben nicht geschlossen, und der Aufruf von recv ist offensichtlich blockierend.
repeat
----- Aber ich bin einen Schritt weiter. Mir ist aufgefallen, dass bei einem verkleinerten Sleep trotzdem teilweise noch Informationen ankommen, und zwar solche, die mittels POST in einem SOAP-Envelope angefragt wurden. Ein Blick in den Code offenbarte dann, dass bei solchen POST-Anfragen mit SOAP kein KeepAlive gesetzt wird, bei allen anderen schon:
Delphi-Quellcode:
Testweise habe ich die if-Bedingung auskommentiert und siehe da: es kommen alle Informationen an, auch mit einem
function THTTPRequest.SendHeader: UTF8String;
[...] if Length(FHTTPSend.Soap.Namespace) = 0 then begin LHeader.Add(Format('Keep-Alive: %d', [KEEP_ALIVE])); LHeader.Add('Connection: Keep-Alive'); end else LHeader.Add('Connection: Close');
Delphi-Quellcode:
in TClient.ReceiveBuffer. Meine Schlussfolgerung: dem Server wurde im Header der Anfrage mitgeteilt, er soll die Verbindung offenhalten, was er offenbar auch tut. Deswegen wartet recv bis zum Empfang von Daten - also vermutlich "endlos".
Sleep(20);
Ich verstehe auch gar nicht, warum da ein KeepAlive angefordert wird. In THTTPRequest.Execute wird die Instanz von TClient unmittelbar nach dem Empfang der Daten sowieso zerstört - und der Socket damit ebenfalls geschlossen. Auszüge aus dem Code:
Delphi-Quellcode:
Wozu die Verbindung über KeepAlive offenhalten, wenn gleich danach der Socket geschlossen werden soll bzw. geschlossen wird:?:
function THTTPRequest.Execute: Boolean;
[...] SendStr := SendHeader + Params; LClient := TClient.Create; try if LClient.Connect then begin LClient.SendBuffer(SendStr, Length(SendStr)); if (LClient.ReceiveBuffer > 0) then begin RcvdHeader(LClient.Header); RcvdContent(LClient.Content); end; end; finally LClient.Free; end; destructor TClient.Destroy; begin if FConnected then Disconnected; inherited; end; function TClient.Disconnected: Boolean; begin Result := WinSock.shutdown(FSocket, SD_BOTH) = 0; if Result then begin FConnected := False; Result := WinSock.CloseSocket(FSocket) = 0; end; end; Grüße Dalai |
AW: Schnellere Kommunikation mit einer Fritzbox
Ich habe den Source Code gerade mal überflogen. Es scheint, dass dort tatsächlich HTTP/1.1 eingesetzt wird. HTTP/1.1 ist etwas komplizierter als HTTP/1.0, da eine Verbindung hier dauerhaft aufrecht erhalten bleibt und für mehrere Requests wiederverwendet wird. Deshalb wird die Verbindung hier nicht geschlossen. Deshalb auch dieses ganze KeepAlive-Gedöhns. Ich persönlich würde das Protokoll der Einfachheit halber auf HTTP/1.0 ändern, da HTTP/1.1 im lokalen Netz sowieso kaum Vorteile hat. Ich weiß jetzt aber nicht, inwieweit sich das auf den Rest des Codes auswirken würde.
|
AW: Schnellere Kommunikation mit einer Fritzbox
Zitat:
Nach Entfernung der KeepAlive-Header wird die Verbindung geschlossen und der Abruf geht schnell; mein Testprogramm braucht dann weniger als eine Sekunde zum Starten, vorher waren es fast fünf (je nach Menge der abgerufenen Informationen). Allerdings hänge ich immer noch an der Abbruch-Bedingung der repeat-Schleife. Ohne eine Verzögerung vor dem Aufruf von recv liefert selbiges keine Daten. Das derzeit benutzte
Delphi-Quellcode:
in der Schleife finde ich nicht so toll. OK, heute funktioniert es sogar ohne Sleep(), was gestern nicht ging. :shock: Hä? Ich werde das wohl beobachten müssen, ob es in den nächsten Tagen weiterhin funktioniert wie vorgesehen...
Sleep(20);
Grüße Dalai |
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:21 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz