AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi XML-String über TCP empfangen
Thema durchsuchen
Ansicht
Themen-Optionen

XML-String über TCP empfangen

Ein Thema von Rungholt · begonnen am 10. Mai 2007 · letzter Beitrag vom 11. Mai 2007
Antwort Antwort
Seite 1 von 2  1 2      
Rungholt

Registriert seit: 20. Apr 2007
19 Beiträge
 
#1

XML-String über TCP empfangen

  Alt 10. Mai 2007, 16:00
Hi,

klingt simple, aber ich tu mich irgendwie schwer damit.
Hat jemand ein Beispiel, wie ich große Strings (XML)
per TCP-Komponente (vorzugsweise über WSocket, oder Indy) empfangen kann ?
Prinzipiell geht das bei mir, nur leider wird der XML-String, den ich über ein
Fremdprogramm empfange, so schnell abgefeuert, dass ich irgendwann nur noch einen
unvollständigen XML-String aus dem Buffer lese. Ich brauche den XML String natürlich
am Stück um ihn korrekt parsen zu können.

Danke schonmal für die Hilfe.

Gruß
Sascha

PS.: Benutze Delphi 7, Indy 7, ICS 7
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#2

Re: XML-String über TCP empfangen

  Alt 10. Mai 2007, 16:44
Hallo!

Du musst den String "in einem Stück" einlesen. Ich selber mache die gesamte Kommunikation eigentlich immer über Streams, die erst komplett empfangen werden und dann verarbeitet.

Im DF habe ich übrigens die SimpleTCP-Komponenten gepostet (basieren auf Indy), die dir da vielleicht auch ein bisschen Arbeit abnehmen.

Cu,
Udontknow
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#3

Re: XML-String über TCP empfangen

  Alt 10. Mai 2007, 16:52
Grundsätzlich werden Daten, die man über das Netzwerk verschickt in einzelne Pakete zerlegt.
TCP bzw. WinSock sorgt dafür, dass die Pakete vollständig und in richtiger Reihenfolge eintreffen.
Du selbst bist aber für das Zusammenhängen der Pakete verantwortlich.
Also muss dann im ReceiveEvent ungefähr folgende Zeile stehen:
Delphi-Quellcode:
   xmldata := xmldata + indySocket.ReceiveString;
// die Funktion ReceiveString hat möglicherweise einen anderen Namen
// ich hab mir nicht die Mühe gemacht die genaue Syntax herauszusuchen
Jetzt hast du vielleicht noch das Problem, dass du das Ende der Übertragung feststellen musst,
damit du dann auf die Daten reagieren kannst.
Entweder du schliest die TCP-Verbindung oder du übermittelst vorher die Anzahl der Nutzdaten.

Vergleiche das mit HTTP:
Code:
HTTP/1.1 200 OK
Server: Apache/1.3.29 (Unix) PHP/4.3.4
Content-Length: (Größe von info.xml in Byte)
Content-Language: de (nach ISO 639 und ISO 3166)
Content-Type: text/xml
<HTML> ....hier die Nutzdaten .....
In Content-Length wird die Länge der Nutzdaten übermittelt, damit der Browser weiss, wie viel er lesen muss.
Andreas
  Mit Zitat antworten Zitat
Rungholt

Registriert seit: 20. Apr 2007
19 Beiträge
 
#4

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 08:42
Danke für die Antworten, aber ich denke ich muss mir was anderes einfallsen lassen. Hier mal ein Beispiel, wie ich die
String-Pakete bekomme:

Paket 1)

<?xml version="1.0" encoding="UTF-16"?>
<DataCaptor ID="{88DB1901-08E1-4012-8EC6-1485E5C04438}">
<DDI ID="{16584EB1-55B2-4BCF-8F3E-48FCDD16769F}">
<TimeStamp ComputerTime="20070511093028.638">
<Variable VarID="58" Value="1160.000030137"/>
<Variable VarID="61" Value="7556.000030653"/>
<Variable VarID="536" Value="6934.000030088"/>
<Variable VarID="537" Value="9150.000018171"/>
.
.
.
</TimeStamp>
</DDI>
</DataCaptor>


Das erste Paket kommt vielleicht noch korrekt (kompletter XML-String)
Aber Irgendwann sieht ein Paket dann so aus:

Paket N)

<Variable VarID="4091" Value="324.000013657"/>
<Variable VarID="4092" Value="8652.00003048"/>
<Variable VarID="4108" Value="2174.000015699"/>
<Variable VarID="250" Value="2668.00001114"/>
</TimeStamp>
</DDI>
</DataCaptor>
<?xml version="1.0" encoding="UTF-16"?>
<DataCaptor ID="{88DB1901-08E1-4012-8EC6-1485E5C04438}">
<DDI ID="{908451A3-0B40-4079-ACCC-E0F28AA1557D}">
<TimeStamp ComputerTime="20070511093029.638">
<Variable VarID="801" Value="3455.000015483"/>
<Variable VarID="807" Value="690.000000182"/>


Und da ich eigentlich keinen Einfuss drauf habe, wie das Paket ankommt, kann ich vermutlich nichts anderes tun,
als immer ein paar Pakete sammeln und dann mit ein bisschen String-Verarbeitung vom ersten Anfangs-Tag bis zum letzten
Ende-Tag den gültigen XML-Bereich zu kopieren und den zu verarbeiten.

Oder sonst noch Ideen ?
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#5

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 08:57
Wie gesagt, packe den String in einen Stream, schicke vorneweg die Size des Streams als Integer, und sende die Daten des Streams. Auf der Gegenseite weisst du genau, wieviele Bytes du nun für das Paket einzulesen hast.

Cu,
Udontknow
  Mit Zitat antworten Zitat
Rungholt

Registriert seit: 20. Apr 2007
19 Beiträge
 
#6

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 09:00
Ich habe nur eine Seite. Ich bin nur der client und habe keinen Einfluß auf den ankommenden XML-String.
Dieser wird von einem externen Programm gesendet. Oder meinst du den ankommenden XML-String in einen Stream packen ?
  Mit Zitat antworten Zitat
Udontknow

Registriert seit: 17. Jun 2002
223 Beiträge
 
#7

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 09:05
Ahso, hast gar keinen Einfluss auf den Sendemechanismus? Das ist tatsächlich was anderes. Dann würde ich es genauso, wie du vorgeschlagen hast, machen: Alles an einen String hängen und auf XML-Tags achten, anhand dieser dann die Pakete ausschneiden...

Cu,
Udontknow
  Mit Zitat antworten Zitat
Rungholt

Registriert seit: 20. Apr 2007
19 Beiträge
 
#8

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 09:07
Richtiiiig.

Ich lass den Thread mal als "offen" stehen, bis ich mit der Implementierung fertig bin.
Vielleicht hat ja noch jemand ne Blitzidee.

Thanx !
Sascha
  Mit Zitat antworten Zitat
Muetze1
(Gast)

n/a Beiträge
 
#9

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 09:10
Du brauchst keine Größenangabe, da du durch die XML Struktur immer feststellen kann, wann diese wieder vollständig (geschlossen ist). Dein grundlegendes Problem ist einfach nur, dass du mehrfach aufgerufen wirst, bis alle Daten empfangen wurden (bzw. du mehrfach Datan abholen musst). Dabei können die Daten an beliebiger Stelle getrennt werden. Von daher folgende Vorgehensweise:

1. Ein Buffer anlegen - am besten dynamisch. Es eignet sich z.B. ein TMemoryStream.
2. Alle abgeholten Datenpackete in diesen Stream schreiben (immer hinten dran)
3. Wenn du mal wieder was in den MemoryStream geschrieben hast, dann kannst du die Daten verarbeiten. Dazu musst du wissen, ob die Daten vollständig sind - und das kann dir dein XML Provider sagen. Der weiss genau, ob die XML Struktur vollständig ist (sprich: gibt es zum Hauptknoten-Tag auch ein schliessendes Tag). Wenn dies der Fall ist, weiss er auch wo die Daten eines XML Packetes aufhören. Damit kannst du diesen Teil vorne aus dem MemoryStream entfernen. Dieses so lange wiederholen bis der MemoryStream eine Grösse von 0 hat (Idealfall, alles interpretierbar, da alles vollständig) oder der XML Provider sagt, dass ist noch nicht vollständig.

So sollte der grundlegende Weg sein. Nun ist offen wie du deinen XML Provider entlocken kannst, wie gross die Daten sind und bis wo in dem Stream eine komplette, gültige Struktur geht und ob sie gültig (komplett) ist.

Die String selber parsen um das Ende zu ermitteln (ob es enthalten ist) wäre ein möglicher Schnellschluss. Wenn der Hauptknoten immer gleich heisst, dann kannst du fest nach dem Ende-Tag des Knotens im String suchen, selber aufteilen und aus dem Stream löschen und entsprechend auch einen schon fertig aufbereiteten Stream deinem XML Provider geben.
  Mit Zitat antworten Zitat
Rungholt

Registriert seit: 20. Apr 2007
19 Beiträge
 
#10

Re: XML-String über TCP empfangen

  Alt 11. Mai 2007, 09:20
Hi Muetze,

ja so in der Art hätte ich es realisiert.
Jetzt entdeckte ich aber glücklicherweise genau die richtige Methode in meiner Indy-Komponente,
die das Problem ganz alleine löst.

Delphi-Quellcode:
while IdTCPClient.Connected do begin
   Memo_Daten.Lines.Add(IdTCPClient.WaitFor('</DataCaptor>'));
   Application.ProcessMessages;
end;
Die Funktion "WaitFor" wartet solang, bis im Receive-Buffer das Ende-Tag </DataCaptor> zu finden ist
und holt erst dann die Daten. Genauso muss es sein.


Danke an alle Beteiligten !
Sascha
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:59 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz