Entwickler-Ecke
Internet / Netzwerk - TIdHTTP, Verbindung unterbrochen?
Stephan.Woebbeking - Do 12.07.12 16:47
Titel: TIdHTTP, Verbindung unterbrochen?
Hallo, ich arbeite mit der TIdHTTP Komponente um Daten auszutauschen. Die serverseitige Protokollbeschreibung lautet (gekürzt, Entwicklungsinformationen) wie folgt:
Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
| [...] The connection is kept open until the update procedure is finished; there’s no need to poll. The [...] sends one line of output at each time that it is able to re-calculate the remaining work with good confidence (there’s no guarantee for a maximum time period or percentage granularity when the progress estimation is updated). [...] > GET /software/update/123456789abcdef/progress HTTP/1.1 > < HTTP/1.1 200 OK < Content-Type: text/plain; charset=UTF-8 < < 134.0 < 130.5 < 127.0 ... time passes ... < 9.0 < 3.0 < 0.0 <
Note that [...] doesn’t send a Content-Length header for the streaming response. The response is complete when the [...] drops the connection. |
Dabei bedeutet ">" vom Client zum Server und "<" vom Server zum Client. Nun bekomme ich zwei solcher Pakete mit dem zeitlichen Abstand von ca. 5,5 Sekunden. Die Information aus dem ersten Paket wird angezeigt, die aus dem zweiten nicht. Die HTTP Verbindung baue ich folgendermaßen auf:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| try httpMonitorConnector.ReadTimeout := 200; httpMonitorConnector.ConnectTimeout := 0; httpMonitorConnector.Response.KeepAlive := True; httpMonitorConnector.Get( '/software/update/' + Connector.ip + ' ' + location + 'progress' ); except on E: EIdReadTimeout do begin MemoLogger.AddToLog( 'Exception as expected: ' + E.ClassName + ' ' + E.Message ); end; end; |
Die Abfrage die ich durch einen Timer durchführe sieht so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8:
| a := -1; if Assigned( httpMonitorConnector.IOHandler ) then begin httpMonitorConnector.IOHandler.CheckForDataOnSource( 5 ); a := httpMonitorConnector.IOHandler.InputBuffer.Size; if ( httpMonitorConnector.IOHandler.InputBuffer.Size > 0 ) then MemoLogger.AddToLog( httpMonitorConnector.IOHandler.ReadLn ); end; logger.Debug( '< Monitor Timer ticked: Assigned: ' + BoolToStr( Assigned( httpMonitorConnector.IOHandler ), True ) + ' Size: ' + IntToStr( a ) ); |
Jetzt weiß ich einfach nicht, warum das erste Paket korrekt angenommen wird, das zweite jedoch nicht? Weitere Pakete kommen dann auch nicht, aber ich denke das Problem liegt eher serverseitig. Wäre es evt. möglich, dass die TCP Verbindung abgebaut wird? Aus Gründen die mir bisher nicht bekannt sind? Falls jemand eine Idee hat, immer her damit!
Danke,
Stephan
jaenicke - Do 12.07.12 17:02
Stephan.Woebbeking hat folgendes geschrieben : |
Wäre es evt. möglich, dass die TCP Verbindung abgebaut wird? Aus Gründen die mir bisher nicht bekannt sind? |
Naja, wo hast du denn eine offen? Ich sehe nichts davon.
Du machst eine Abfrage auf dem Server mit Get, mehr nicht, sprich verbinden, Seite abrufen, Verbindung schließen. Das ist bei HTTP so gedacht.
Wenn du eine TCP-Verbindung offen halten willst, dann musst du auch einen expliziten TCP-Client benutzen. Ich glaube nicht, dass du da mit TIdHttp weiterkommst...
Martok - Do 12.07.12 20:17
Das ist
Comet [
http://en.wikipedia.org/wiki/Comet_%28programming%29], ich bin mir relativ sicher dass das mit Indy nicht unfallfrei geht. Wir hatten letztes Jahr im AGS bei der Brett-KI eigentlich Long Polling vorgesehen, das hab ich jedenfalls nicht stabil bekommen. Und das ist noch einfach, weil's nur ein normaler Request ist, der halt länger dauert. Mindestens muss der Request in einem Thread passieren, da Get() den Thread blockiert und damit dein Timer gar nicht tickt (nur einmal, ganz am Ende).
Was mit der Connection passiert, findest du wohl am einfachsten mit Wireshark raus. Falls einer die Verbindung abbricht, sieht man das ja spätestens auf TCP-Ebene.
Stephan.Woebbeking - Mo 16.07.12 17:56
Ok, dann habe ich jetzt mal den Verbindungsaufbau so umgeändert:
Delphi-Quelltext
1: 2: 3: 4:
| TcpClient1.RemoteHost := Connector.ip; TcpClient1.RemotePort := '80'; TcpClient1.Connect; TcpClient1.Sendln( 'GET ' + location + 'progress HTTP/1.1' ); |
Und die Nutzung der Verbindung (Timer) dann so:
Delphi-Quelltext
1: 2: 3: 4: 5:
| ret := TcpClient1.WaitForData( 5 ); if ( ret ) then begin line := TcpClient1.Receiveln; MemoLogger.AddToLog( line ); end; |
Ich bekomme aber über diese Verbindung GAR KEINE Daten. Obwohl sie im Netzwerk (Wireshark) übertragen werden. Wende ich die Komponente falsch an? Die Ausführung über den Timer erfolgt, das habe ich anhand eines Breakpoints überprüft. Allerdings liefert WaitForData() nie True zurück, obwohl ich hier eine Signalisierung erwarten würde, sobald Daten anstehen. So gesehen ist das aber noch schlimmer als die ursprüngliche Lösung. Bei der habe ich übrigens herausgefunden, dass dort in einem Paket das FIN Flag gesetzt und das nächste kommende Packet mittels RST, ACK abgewehrt wird. Woran kann das liegen? Kann ich das unterbinden?
Stephan
Stephan.Woebbeking - Fr 20.07.12 09:15
Niemand eine Idee dazu???
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 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!