![]() |
TcpClient - Antwort XML unvollständig.
Liste der Anhänge anzeigen (Anzahl: 1)
Mit Tcpclient wird an die Fritzbox diese Nachricht geschickt:
Code:
Mit diesem Code
POST /upnp/control/WANIPConn1 HTTP/1.1
Host: fritz.box:49000 Accept: */* Content-Type: text/xml SoapAction:urn:schemas-upnp-org:service:WANIPConnection:1#GetStatusInfo Content-Length: 263 <?xml version="1.0"?> <s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"> <s:Body> <u:GetStatusInfo xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1" /> </s:Body> </s:Envelope>
Delphi-Quellcode:
erhalte ich als Ergebnis:
procedure TForm1.Button1Click(Sender: TObject);
var TcpClient1 : TTcpClient; begin TcpClient1 := TTcpClient.Create(nil); TcpClient1.RemoteHost := Edit1.Text; TcpClient1.RemotePort := Edit2.Text; TcpClient1.OnReceive := TcpReceive; TcpClient1.OnError := TcpError; TcpClient1.Connect; try TcpClient1.Sendln(Memo2.Text); finally TcpClient1.Disconnect; end; TcpClient1.Destroy; end; procedure TForm1.TcpReceive(Sender: TObject; Buf: PAnsiChar; var DataLen: Integer); begin Memo1.Lines.Add(Buf); end; procedure TForm1.TcpError(Sender: TObject; SocketError: Integer); begin ShowMessage(Format('Fehler: %d', [SocketError])); end;
Code:
Da fehlt leider etwas.
HTTP/1.1 200 OK
DATE: Fri, 14 Jan 2011 21:51:41 GMT SERVER: FRITZ!Box Fon WLAN 7320 UPnP/1.0 AVM FRITZ!Box Fon WLAN 7320 (UI) 100.04.88 CONNECTION: keep-alive CONTENT-LENGTH: 430 CONTENT-TYPE: text/xml; charset="utf-8" EXT: <?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body> <u:GetStatusInfoResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"> <NewConnectionStatus>Connected</NewConne Man kann SendLn und ReceiveLn so oft aufrufen bis die Datei vollständig ist. Das sieht dann so aus:
Code:
Was mache ich falsch? Es muss doch möglich sein, die ganze Datei sofort mit einem Aufruf zu erhalten?
HTTP/1.1 200 OK
DATE: Fri, 14 Jan 2011 22:02:45 GMT SERVER: FRITZ!Box Fon WLAN 7320 UPnP/1.0 AVM FRITZ!Box Fon WLAN 7320 (UI) 100.04.88 CONNECTION: keep-alive CONTENT-LENGTH: 430 CONTENT-TYPE: text/xml; charset="utf-8" EXT: <?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body> <u:GetStatusInfoResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"> <NewConnectionStatus>Connected</NewConnectionStatus> <NewLastConnectionError>ERROR_NONE</NewLastConnectionError> <NewUptime>35312</NewUptime> </u:GetStatusInfoResponse> </s:Body> </s:Envelope>HTTP/1.1 200 OK |
AW: TcpClient - Antwort XML unvollständig.
Hallo Garfield,
eventuell ist das von Dir angehängte Projekt ja anders aufgebaut, aber der in deinem Beitrag gezeigte Delphi-Code sieht irgendwie falsch aus. Lies mal ![]() Grüße vom marabu |
AW: TcpClient - Antwort XML unvollständig.
Ich glaube mal ganz einfach, das würde ich auch ohne den Verweis in dem Post drüber denken, dass du Nach dem Send() viel zu schnell dein Disconnect() aufrufst. Der TCP-Client beendet dann schon die Verbindung, bevor alles da ist, was da sein sollte. Oder er zeigt dir nur das erste von 2 Paketen an. Das 2. Paket wird dann von dir ignoriert, weil du schon die Verbindung wieder geschlossen hast.
Bernhard |
AW: TcpClient - Antwort XML unvollständig.
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Zitat:
Wenn ich die Antwort zeilenweise bis zur zweiten Leerzeile lese:
Delphi-Quellcode:
bekomme ich sofort:
procedure TForm1.Button2Click(Sender: TObject);
var TcpClient1 : TTcpClient; temp : String; count : Integer; begin Button1.Enabled := False; Memo1.Clear; TcpClient1 := TTcpClient.Create(nil); TcpClient1.RemoteHost := Edit1.Text; TcpClient1.RemotePort := Edit2.Text; TcpClient1.OnError := TcpError; try if TcpClient1.Connect then begin TcpClient1.SendLn(Memo2.Text); temp := TcpClient1.Receiveln(); count := 0; while count <= 1 do begin Memo1.Lines.Add(temp); temp := TcpClient1.Receiveln; if Length(temp) = 0 then inc(count); end; end; finally TcpClient1.Close; TcpClient1.Destroy; end; Button1.Enabled := True; end;
Code:
und etwa 30 s später die letzte Zeile:
HTTP/1.1 200 OK
DATE: Sat, 15 Jan 2011 15:05:35 GMT SERVER: FRITZ!Box Fon WLAN 7320 UPnP/1.0 AVM FRITZ!Box Fon WLAN 7320 (UI) 100.04.88 CONNECTION: keep-alive CONTENT-LENGTH: 430 CONTENT-TYPE: text/xml; charset="utf-8" EXT:
Code:
<?xml version="1.0"?>
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body> <u:GetStatusInfoResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"> <NewConnectionStatus>Connected</NewConnectionStatus> <NewLastConnectionError>ERROR_NONE</NewLastConnectionError> <NewUptime>47504</NewUptime> </u:GetStatusInfoResponse> </s:Body> </s:Envelope> |
AW: TcpClient - Antwort XML unvollständig.
Mit TIdTcpClient kommt man auch nicht weiter.
Delphi-Quellcode:
Das XML wird zwar in mehreren Zeilen zurückgegeben, aber bei der letzten Zeile hängt es dann.
procedure TForm1.Button2Click(Sender: TObject);
var TcpClient : TIdTcpClient; temp : String; count : Integer; begin Memo1.Clear; TcpClient := TIdTcpClient.Create(nil); TcpClient.Host := Edit1.Text; TcpClient.Port := StrToInt(Edit2.Text); try TcpClient.Connect; if TcpClient.Connected then begin if TcpClient.IOHandler.Connected then begin TcpClient.IOHandler.Write(Memo2.Text); temp := TcpClient.IOHandler.ReadLn; count := 0; while count <= 1 do begin Memo1.Lines.Add(temp); temp := TcpClient.IOHandler.ReadLn; if Length(temp) = 0 then inc(count); end; end; end; finally TcpClient.Disconnect; TcpClient.Destroy; end; end; |
AW: TcpClient - Antwort XML unvollständig.
Ich bin mir jetzt nicht ganz sicher, aber sollte nicht IdHTTPClient ausreichen?
Bernhard |
AW: TcpClient - Antwort XML unvollständig.
Guten Abend,
wenn aus dem Buffer mit readeLn gelesen wird, dann wird nur eine Zeile (bis zum ersten CR LF) gelesen. Ich meine es wäre besser, solange aus dem Buffer zu lesen bis InputBufferIsEmpty = true ist. Grüße Klaus |
AW: TcpClient - Antwort XML unvollständig.
Einen IdHTTPClient finde ich nicht, nur den IdHTTPseerver. :?:
Zitat:
|
AW: TcpClient - Antwort XML unvollständig.
.. hatte mir das in etwa so vorgestellt:
Delphi-Quellcode:
[ungetestet]
procedure TForm1.Button2Click(Sender: TObject);
var TcpClient : TIdTcpClient; temp : String; count : Integer; begin Memo1.Clear; TcpClient := TIdTcpClient.Create(nil); TcpClient.Host := Edit1.Text; TcpClient.Port := StrToInt(Edit2.Text); try TcpClient.Connect; if TcpClient.Connected then begin if TcpClient.IOHandler.Connected then begin TcpClient.IOHandler.Write(Memo2.Text); while not tcpClient.IOHandler.InputBufferIsEmpty do begin temp := TcpClient.IOHandler.ReadLn; Memo1.Lines.Add(temp); end; end; end; finally TcpClient.Disconnect; TcpClient.Destroy; end; end; Grüße Klaus |
AW: TcpClient - Antwort XML unvollständig.
Zitat:
Bernhard |
AW: TcpClient - Antwort XML unvollständig.
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
Code:
HTTP/1.1 500 Internal Server Error
DATE: Sat, 15 Jan 2011 23:17:24 GMT SERVER: FRITZ!Box Fon WLAN 7320 UPnP/1.0 AVM FRITZ!Box Fon WLAN 7320 (UI) 100.04.88 CONNECTION: keep-alive CONTENT-LENGTH: 434 CONTENT-TYPE: text/xml; charset="utf-8" <?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <s:Body> <s:Fault> <faultcode>s:Client</faultcode> <faultstring>UPnPError</faultstring> <detail> <UPnPError xmlns="urn:schemas-upnp-org:control-1-0"> <errorCode>401</errorCode> <errorDescription>invalid action</errorDescription> </UPnPError> </detail> </s:Fault> </s:Body> </s:Envelope> Zitat:
|
AW: TcpClient - Antwort XML unvollständig.
Liste der Anhänge anzeigen (Anzahl: 1)
Auf der Suche nach der Fehlermeldung fand ich diese Lösung: Die gesendete und empfangene Nachricht enden mit dem selben schließenden Tag. Deshalb funktioniert dies:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var TcpClient : TIdTcpClient; begin Memo1.Clear; TcpClient := TIdTcpClient.Create(nil); TcpClient.Host := 'fritz.box'; TcpClient.Port := 49000; try TcpClient.Connect; if TcpClient.Connected then begin if TcpClient.IOHandler.Connected then begin TcpClient.IOHandler.Write(Memo3.Text); Memo1.Text := TcpClient.IOHandler.WaitFor(Memo3.Lines.Strings[Memo3.Lines.Count - 1]); Memo1.Lines.Add(Memo3.Lines.Strings[Memo3.Lines.Count - 1]); end; end; finally TcpClient.Disconnect; TcpClient.Destroy; end; end;
Code:
Das einzige, was etwas stört, sind die "falschen" Zeilenschaltungen im XML.
HTTP/1.1 200 OK
DATE: Sun, 16 Jan 2011 00:20:28 GMT SERVER: FRITZ!Box Fon WLAN 7320 UPnP/1.0 AVM FRITZ!Box Fon WLAN 7320 (UI) 100.04.88 CONNECTION: keep-alive CONTENT-LENGTH: 430 CONTENT-TYPE: text/xml; charset="utf-8" EXT: <?xml version="1.0"?> <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><s:Body> <u:GetStatusInfoResponse xmlns:u="urn:schemas-upnp-org:service:WANIPConnection:1"> <NewConnectionStatus>Connected</NewConnectionStatus> <NewLastConnectionError>ERROR_NONE</NewLastConnectionError> <NewUptime>80745</NewUptime> </u:GetStatusInfoResponse> </s:Body> </s:Envelope> Anscheinend ist es ein Fehler in der verwendeten Indy-Version. |
AW: TcpClient - Antwort XML unvollständig.
Der Fehler scheint in meiner Fritzbox zu stecken. Bei der Antwort fehlt in der letzten Zeile das LF (#10). Deshalb wartet Indy auf weitere Daten bis die Verbindung geschlossen wird.
___ Nachtrag: Oben hatte ich die Indy 10-Version welche bei TurboDelphi dabei war verwendet. Bei der aktuellen Indy 10 wird beim WaitFor der angegebene Text mit zurück gegeben. |
AW: TcpClient - Antwort XML unvollständig.
Bei einer vernünftigen Kommunikation sollte am Anfang die Länge der übertragenen Nachricht übermittelt werden, dann ist das Ende Zeichen sowas von überflüssig.
Schau dir die Nachricht mal als Hex an, ob da am Anfang nicht diese Information mitkommt. Im Header steht aber auch eine Information zum Anzahl der Zeichen. Versuche ansonsten diese auszuwerten |
AW: TcpClient - Antwort XML unvollständig.
Indy reserviert für die Antwort 32 kB. Nach der Ermittlung der Antwortlänge wird die Antwort in einem entsprechend großen Buffer geschrieben. Im Beispiel sind es 663 Byte.
ReadLn ruft ReadLn(LF) auf und die function TIdBuffer.IndexOf(const AString: string; AStartPos: Integer): Integer; ermittelt die Position des nächsten LF. Beim letzten String wird die Funktion einfach beendet und anstelle der Länge des letzten Strings -1 zurückgegeben. |
AW: TcpClient - Antwort XML unvollständig.
Delphi-Quellcode:
Geändert in
function TIdBuffer.IndexOf(const ABytes: TIdBytes; AStartPos: Integer): Integer;
var i, j, LEnd, BytesLen: Integer; LFound: Boolean; begin Result := -1; // Dont search if it empty if Size > 0 then begin EIdException.IfTrue(Length(ABytes) = 0, RSBufferMissingTerminator); EIdException.IfNotInRange(AStartPos, 0, Size - 1, RSBufferInvalidStartPos); BytesLen := Length(ABytes); LEnd := FHeadIndex + Size; for i := FHeadIndex + AStartPos to LEnd - BytesLen do begin LFound := True; for j := 0 to BytesLen - 1 do begin if i + j < LEnd then begin if FBytes[i + j] <> ABytes[j] then begin LFound := False; Break; end; end else Break; end; if LFound then begin Result := i - FHeadIndex; if Result <> -1 then Break; end; end; end; end;
Delphi-Quellcode:
und es funktioniert.
function TIdBuffer.IndexOf(const ABytes: TIdBytes; AStartPos: Integer): Integer;
var i, j, LEnd, BytesLen: Integer; LFound: Boolean; begin Result := -1; // Dont search if it empty if Size > 0 then begin EIdException.IfTrue(Length(ABytes) = 0, RSBufferMissingTerminator); EIdException.IfNotInRange(AStartPos, 0, Size - 1, RSBufferInvalidStartPos); BytesLen := Length(ABytes); LEnd := FHeadIndex + Size; for i := FHeadIndex + AStartPos to LEnd - BytesLen do begin LFound := True; for j := 0 to BytesLen - 1 do begin { * Beim letzten Zeichen des Buffer ist auf jeden Schluss. } if i + j < LEnd - 1 then begin if FBytes[i + j] <> ABytes[j] then begin LFound := False; Break; end; end else Break; end; if LFound then begin Result := i - FHeadIndex; if Result <> -1 then Break; end; end; end; end; |
AW: TcpClient - Antwort XML unvollständig.
Zitat:
Da muss dann noch die function TIdIOHandler.ReadLn(ATerminator: string; ATimeout: Integer = IdTimeoutDefault; AMaxLineLength: Integer = -1): string; ein wenig angepasst werden.
Delphi-Quellcode:
Wobei ich mich frage, ob man da ein
// Extract actual data
Result := FInputBuffer.Extract(LTermPos + Length(ATerminator)); if (ATerminator = LF) and (LTermPos > 0) then begin { * Wenn beim letzten String das LF fehlt, würde das letzte Zeichen abgeschnitten. } if (Result[LTermPos + 1] <> CR) and (Result[LTermPos + 1] <> LF) then inc(LTermPos); if Result[LTermPos] = CR then begin Dec(LTermPos); end; end; SetLength(Result, LTermPos); end;
Delphi-Quellcode:
nicht ausreichend wäre.
// Extract actual data
Result := FInputBuffer.Extract(LTermPos + Length(ATerminator)); Result := TrimRight(Result); end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:59 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