Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   XML (https://www.delphipraxis.net/46-xml/)
-   -   Delphi RPC und Delphi 2009 (https://www.delphipraxis.net/132879-rpc-und-delphi-2009-a.html)

alphaflight83 21. Apr 2009 10:58


RPC und Delphi 2009
 
Tag auch,

ich hätte auch mal wieder ein Problem.
Ich hatte ein Delphi 7 Programm, das einige XML-RPC Funktionen verwendet hat.
( aus xmlrpctypes, xmlrpcclient)
RpcCaller : TRpcCaller;
RpcFunction : IRpcFunction;
RpcResult : IRpcResult;

Nun läuft die Version 2.0 von XML-RPC nicht mehr mit Delphi 2009 auf die ich nun umstelle,
was mich zu der Frage bringt, welche Vorgehensweise hier am sinnvollsten ist:
1. Auf andere Komponenten wechseln und wenn ja welche, oder
2. Die XML-RPC versuchen in Gang zu bringen

Wäre schön, wenn mir jemand weiterhelfen könnte.

Gruß

mkinzler 21. Apr 2009 11:00

Re: RPC und Delphi 2009
 
Zitat:

Nun läuft die Version 2.0 von XML-RPC nicht mehr mit Delphi 2009 auf die ich nun umstelle,
Wie äussert sich das?

alphaflight83 21. Apr 2009 12:19

Re: RPC und Delphi 2009
 
Nunja, wenn ich die XML-RPC mit D2009 verwenden will nehme ich an, dass ich die auch damit kompilieren muss.
Beim kompiliervorgang kommen dann aber zahlreiche Fehler, die wohl mit der Umstellung auf Utf8 zusammenhängen.
Jetzt gings mir eben darum, ob es hier eine Aktualisierung gibt, ob das mittlerweile sowieso alles anders gemacht wird,
oder ob ich mich einfach zu dumm anstelle.

mkinzler 21. Apr 2009 12:24

Re: RPC und Delphi 2009
 
Dann zeig doch mal die Fehlermeldungen :zwinker:

mjustin 21. Apr 2009 12:28

Re: RPC und Delphi 2009
 
Zitat:

Zitat von alphaflight83
Tag auch,

ich hätte auch mal wieder ein Problem.
Ich hatte ein Delphi 7 Programm, das einige XML-RPC Funktionen verwendet hat.
( aus xmlrpctypes, xmlrpcclient)
RpcCaller : TRpcCaller;
RpcFunction : IRpcFunction;
RpcResult : IRpcResult;

Nun läuft die Version 2.0 von XML-RPC nicht mehr mit Delphi 2009 auf die ich nun umstelle,
was mich zu der Frage bringt, welche Vorgehensweise hier am sinnvollsten ist:
1. Auf andere Komponenten wechseln und wenn ja welche, oder
2. Die XML-RPC versuchen in Gang zu bringen

Wäre schön, wenn mir jemand weiterhelfen könnte.

Gruß

Hier sind zwei Kandidaten:

REMObjects SDK- http://www.remobjects.com/ro.aspx
Pros:
Free .NET client (great for calling Delphi from ASP)
SOAP server
FreePascal support
XMLRPC

RealThinClient- http://www.realthinclient.com
Pros:
Extemely flexible
FreePascal support
XMLRPC

(zitiert aus: https://forums.codegear.com/message....essageID=84775)

alphaflight83 21. Apr 2009 12:37

Re: RPC und Delphi 2009
 
Nuja, zum Beispiel tritt in dieser Funktion ein E2010: Inkompatible Typen - Fehler auf.

Delphi-Quellcode:
FUNCTION Utf8ToAnsi (Source : STRING; UnknownChar : CHAR = '¿') : ANSISTRING; // <- Result: AnsiString
          (* Converts the given UTF-8 String to Windows ANSI (Win-1252).
             If a character can not be converted, the "UnknownChar" is inserted. *)
VAR
  SourceLen : INTEGER; // Length of Source string
  I, K     : INTEGER;
  A        : BYTE;    // Current ANSI character value
  U        : WORD;
  Ch       : CHAR;    // Dest char
  Len      : INTEGER; // Current real length of "Result" string
BEGIN
  SourceLen := Length (Source);
  SetLength (Result, SourceLen);  // Enough room to live
  Len := 0;
  I  := 1;
  WHILE I <= SourceLen DO BEGIN
    A := ORD (Source [I]);
    IF A < $80 THEN BEGIN                                              // Range $0000..$007F
      INC (Len);
      Result [Len] := Source [I]; // ---> Fehlermeldung: E2010: Inkompatible Typen: AnsiChar und Char (Source : String, Result : AnsiString)
      INC (I);
      END
    ELSE BEGIN                                                         // Determine U, Inc I
      IF (A AND $E0 = $C0) AND (I < SourceLen) THEN BEGIN              // Range $0080..$07FF
        U := (WORD (A AND $1F) SHL 6) OR (ORD (Source [I+1]) AND $3F);
        INC (I, 2);
        END
      ELSE IF (A AND $F0 = $E0) AND (I < SourceLen-1) THEN BEGIN       // Range $0800..$FFFF
        U := (WORD (A AND $0F) SHL 12) OR
             (WORD (ORD (Source [I+1]) AND $3F) SHL 6) OR
             (      ORD (Source [I+2]) AND $3F);
        INC (I, 3);
        END
      ELSE BEGIN                                                       // Unknown/unsupported
        INC (I);
        FOR K := 7 DOWNTO 0 DO
          IF A AND (1 SHL K) = 0 THEN BEGIN
            INC (I, (A SHR (K+1))-1);
            BREAK;
            END;
        U := WIN1252_UNICODE [ORD (UnknownChar)];
        END;
      Ch := UnknownChar;                                               // Retrieve ANSI char
      FOR A := $00 TO $FF DO
        IF WIN1252_UNICODE [A] = U THEN BEGIN
          Ch := CHR (A);
          BREAK;
          END;
      INC (Len);
      Result [Len] := Ch; // ---> Fehlermeldung: E2010: Inkompatible Typen: AnsiChar und Char (Ch : Char , Result : AnsiString)
      END;
    END;
  SetLength (Result, Len);
END;
Hier stellt sich nun die Frage, ob man die Funktionen (gibts auch rückwärts, die ist aber fehlerfrei)
überhaupt noch benötigt.
Hab mich mit dem Code noch nicht eingehend befasst, wollte das eben auch möglichst vermeiden.
Aber anscheinend sind alle Äpfel sauer, in die ich hier beissen kann.

@mjustin: Danke mal für die Alternativen
Allerdings kommen beide für mich nicht in Frage, da der Einsatz sich auf einige wenige Zugriffe beschränkt und der Preis somit
kaum zu rechtfertigen ist.

mkinzler 21. Apr 2009 13:15

Re: RPC und Delphi 2009
 
String / Char -> Ansistring/AnsiChar

alphaflight83 21. Apr 2009 13:38

Re: RPC und Delphi 2009
 
Wenn das alles wäre, wäre mir das schon klar. Mir geht es aber eher darum ob das Gesamtkonzept in dieser Form noch funktioniert.
Wenn ich einen Char hier mit einem AnsiChar ersetze, zieht sich das wie ein Rattenschwanz durch den ganzen Code.
Der Aufwand den kompletten XML-RPC Code zu durchforsten wird dann doch relativ groß.

mjustin 21. Apr 2009 14:29

Re: RPC und Delphi 2009
 
Zitat:

Zitat von alphaflight83
Wenn das alles wäre, wäre mir das schon klar. Mir geht es aber eher darum ob das Gesamtkonzept in dieser Form noch funktioniert.
Wenn ich einen Char hier mit einem AnsiChar ersetze, zieht sich das wie ein Rattenschwanz durch den ganzen Code.
Der Aufwand den kompletten XML-RPC Code zu durchforsten wird dann doch relativ groß.

Alternativ könnte man auch AnsiString überall mit "string" ersetzen, ausser da, wo ein UTf-8 String benötigt wird. Den kann man z.B. mit Utf8Encode / Utf8Decode konvertieren, und die gepostete Funktion ist damit ersetzbar.

Aber das mit dem Rattenschwanz stimmt schon ...

alphaflight83 21. Apr 2009 15:48

Re: RPC und Delphi 2009
 
Okay, hab mich jetzt mal an den Rattenschwanz gewagt und fröhlich Ansis erschlagen.
Hänge nun aber an einem Punkt in der Datei XmlRpcClient an dem die Funktion
Delphi-Quellcode:
HashMessageDigest := TIdHashMessageDigest5.Create;
  try
    { determine the md5 digest hash of the request }
    Hash := Hash128AsHex(HashMessageDigest.HashValue(XmlRequest)); // <-
aufgerufen wird.
Jetzt bin ich mir nicht ganz sicher ob ich mich hier schon verrant habe.
Eine Methode Hashvalue konnte ich in HashMessageDigest samt aller Mutter, Grußmutter ... -Klassen nicht finden.
Mit allen anderen vorhandenen Methoden hauts auch nicht hin.
Hash128ToHex will einen Übergabewert vom Typ T4x4LongWordRecord.
Aus Indy's IdHashMessageDigest:
Delphi-Quellcode:
T4x4LongWordRecord = array[0..3] of LongWord;
Das einzige Attribut das diesen Typ aufweist ist FState in der Mutterklasse TIdHashMessageDigest4 und liegt protected vor.

Edit: HashValue gibt es allerdings in den Klassen TIdHash16 und TIdHash32 die genau wie die TIdHashMessageDigests von TIdHash erben ... :coder2:

mjustin 21. Apr 2009 16:18

Re: RPC und Delphi 2009
 
Delphi-Quellcode:
HashMessageDigest := TIdHashMessageDigest5.Create;
  try
    { determine the md5 digest hash of the request }
    Hash := Hash128AsHex(HashMessageDigest.HashValue(XmlRequest)); // <-
Indy muss auf jeden Fall auf die neue Tiburon-Version upgedated werden, aber der XML-RPC Code scheint etwas älter zu sein.
Es gibt aber auch in der neuen Indy Version MD5 Funktionen, die den gewünschten Hash liefern sollten. Nur heissen sie jetzt wahrscheinlich anders.

Meine Indy-basierte MD5 Funktion sieht so aus:
Delphi-Quellcode:
function MD5Hash(const Input: WideString): string;
begin
  with TIdHashMessageDigest5.Create do
  try
    Result := LowerCase(HashStringAsHex(string(Input)));
  finally
    Free;
  end;
end;

alphaflight83 22. Apr 2009 10:47

Re: RPC und Delphi 2009
 
Joa, mit deiner MD5 Funktion kompiliert es, allerdings wirft Indy (idHTTP) bei der Ausführung Fehler.
Wärs gelaufen hätte ich mich gefreut wie'n Schnitzel, aber so müsste ich jetzt doch tiefer in die Thematik einsteigen,
als ich das eigentlich wollte.
Da die mMn größte Problematik hier der verwendete XML-Parser ist, der nur begrenzte Unicode Unterstützung mitbringt,
muss man sich wohl damit mal genauer auseinandersetzen, bzw. einen adäquaten Ersatz finden.

PS: Wenn jemand natürlich den Stein der Weisen zu diesem Thema parat hat ... :wink:

alphaflight83 23. Apr 2009 10:33

Re: RPC und Delphi 2009
 
Liste der Anhänge anzeigen (Anzahl: 1)
So hab jetzt doch noch mal versucht was Vernünftiges zu Stande zu bringen,
bin aber nach erfolgreichem Kompilieren wieder an der Ausführung gescheitert:

EIdHttpProtocolException HTTP/1.0 500 Internal Error
The server encountered an unexpected condition which prevented it from fulfilling the request.


Unter Delphi 7 mit XML-RPC-2.0.0 funktioniert das ganze mit dem selben Aufruf ohne Probleme.

In LibXmlParser.pas hab ich folgende Änderungen vorgenommen
(Alle Änderungen im Code durch Note (SeHa-2009-04-23) gekennzeichnet)
- Die AnsiToUtf8 und Utf8ToAnsi Funktionen auskommentiert
- Special Helper Functions rausgenommen, da die zu Fehlern geführt haben.
- TranslateEncoding schleift nur noch durch:

Delphi-Quellcode:
FUNCTION TXmlParser.TranslateEncoding (CONST Source : STRING) : STRING;
BEGIN
  Result := Source;
END;
In XmlRpcCommon.pas:
- IdHashMessageDigest eingebunden
- Funktion eingefügt: function HashStringMD5AsHex(const AStr: WideString): string; welche der Funktion von mjustin entspricht
In XmlRpcClient.pas:
- Bekannte benötigte Änderungen für Indy10 eingesetzt
- In TRpcCaller.Execute HashStringMD5AsHex Funktion eingesetzt
Delphi-Quellcode:
  { determine the md5 digest hash of the request }
  // Hash := Hash128AsHex(HashMessageDigest.HashValue(XmlRequest));
  Hash := HashStringMD5AsHex(XmlRequest);
In XmlRpcServer.pas:
- IdContext eingebunden
- Bekannte benötigte Änderungen für Indy10 eingesetzt
DiMime.pas: durch aktuellere Version ersetzt

Wie gesagt, hat es nach den Änderungen kompiliert (Auch ohne dass Ansi-Strings und -Chars ersetzt wurden)
Aber bei der Ausführung kommt besagter Fehler.

Hab das ganze Gedönz mal angehängt.

alphaflight83 15. Jun 2009 12:54

Re: RPC und Delphi 2009
 
Ab heute gibt es den Real Thin Client (RTC) unter der freien BSD Lizenz.
Hiermit sollte sich dann das leidige Thema RPC auf D2009 vernünftig lösen lassen.
(Edit: Wodurch dann für mich auch die Änderungsversuche am XML-RPC hinfällig werden)

himitsu 15. Jun 2009 13:32

Re: RPC und Delphi 2009
 
hatte mir grad mal dieses XML-RPC angesehn und sowas find ich schon witzig ... wozu haben die da XML-Klassen verwaut, wo sie nichtmal genutzt werden? :shock:
Delphi-Quellcode:
function TRpcFunction.GetRequestXML: string;
var
  Strings: TStrings;
begin
  Strings := TStringList.Create;
  try
    Strings.Add('<?xml version="1.0"?>' + #13#10);
    Strings.Add('<methodCall>' + #13#10);
    Strings.Add('  <methodName>' + FObjectMethod + '</methodName>' + #13#10);
    GetBodyXML(Strings);
    Strings.Add('</methodCall>' + #13#10);
    Result := Strings.Text;
  finally
    Strings.Free;
  end;
end;
nja, und den darin verwendeten LibXmlParser hatte ich auch noch nicht so richtig unter D09 zum Laufen gebracht.

alphaflight83 15. Jun 2009 14:45

Re: RPC und Delphi 2009
 
Jo, ich hatte mich etwas darin verrannt den Parser umschreiben zu wollen,
woran ich gescheitert bin. Dann wollte ich den Parser ersetzen, bin aber nach gottseidank nur kurzer Versuchszeit
heute auf die Nachricht beim RTC gestoßen. Jetzt versuch ich mich mal daran.

himitsu 15. Jun 2009 14:54

Re: RPC und Delphi 2009
 
Also einen in D09 laufenden Parser hab ich ja ... nur kenn ich mich mit diesem RPC nicht so aus und da wäre es schwer nun etwas dafür zu machen,
wobei der Aufbau der XML-Dateien schonmal recht einfach gestaltet ist.

Wie nutzt man es denn programmseitig?

alphaflight83 16. Jun 2009 07:29

Re: RPC und Delphi 2009
 
Die Antwort wird dir wahrscheinlich nicht sehr viel bringen, da ich zur komplizierten Seite, dem Server leider gar nichts sagen kann,
da das ein Kollege in Python geschrieben hat.
Der Aufruf auf Client-Seite ist simpel, da nur die Eigenschaften EndPoint, ObjectMethod sowie Ip-Adresse und Port benötigt werden.

Beispiel-Aufruf:
Das Programm würde hier eine Beschreibung zu einem Item anhand seiner ItemID aus einer serverseitig hinterlegten Liste holen.
(Wie gesagt, die eigentliche Logik steckt dabei im Serverprogramm.)

Delphi-Quellcode:
(**********************************
** Function: RPC_ItemDescription **
**********************************)
function RPC_ItemDescription (IP_Address: String; TCP_Port, ItemID : Integer):LongInt;
var
  RpcCaller   : TRpcCaller;
  RpcFunction : IRpcFunction;
  RpcResult   : IRpcResult;
begin
  RpcCaller := TRpcCaller.Create;
  try
    RpcCaller.EndPoint := '/RPC2';
    RpcCaller.HostName := IP_Address;
    RpcCaller.HostPort := TCP_Port;

    RpcFunction             := TRpcFunction.Create;
    RpcFunction.ObjectMethod := 'get_item_descr';
    RpcFunction.AddItem       (ItemID);

    RpcResult := RpcCaller.Execute(RpcFunction);
    Result := RpcResult.AsInteger;
  finally
    RpcCaller.Free;
  end;
end;

himitsu 16. Jun 2009 08:16

Re: RPC und Delphi 2009
 
Also im Prinzip wird nur eine XML-Datei zusammengebastelt,
wo ein Funktionsname und Parameter eingetragen werden.
Dann wird das via TCPIP an eine IP+Port versendet,
man bekommt eine neue XML-Datei zurück und sucht da das Ergebnis raus.

Also im eigenem Programm werden keine Funktionen aufgerufen?

Na da sollte sich ja,
wenn die Parameter nicht all zu aufwändig und Exotisch ausfallen,
was mit einer kleinen Klasse machen lassen. :stupid:

Müßte ich nur mal sehn, wie ich das mit dem Internetversand hinbekomm.

alphaflight83 16. Jun 2009 09:00

Re: RPC und Delphi 2009
 
Joa, möglich, dass das nicht allzu komplex ist, wenn man sich da allerdings ohne XML Vorwissen reinwirft,
kann das schnell ganz schön viel werden. :gruebel:

Das Problem dabei ist nur, dass das ganze XML-RPC kompatibel bleiben muss, da das eben in nahezu jeder Sprache verfügbar ist.
Edit: Wie gesagt, Mit Delphi 7 war die Sache für mich mit Aufrufen der gezeigten Größenordnung erledigt.
Mit dem Thema selbst musste ich mich da nicht allzu sehr befassen. Meine gescheiterten Versuche mit dem Parser haben mir dann eher
Frust als Lust bereitet.

himitsu 16. Jun 2009 09:14

Re: RPC und Delphi 2009
 
für die XML selber dürfte es reichen sie ohne Codierinfo zu erstellen, dann wäre sie per Standard UTF-8-kodiert und das dürfte mit der Ansi- bzw. ASCII-Kodierung vereinbar sein, welche dieses nicht mehr funktionierende XML-RPC-Teil verwendet ... steht leider nirgends, welches es genau ist, aber egal.

Da sie es nicht angeben und XML laut den XML-Spezifikationen standardmäßig UTF-8 ist, wär das vermutlich dennoch OK.

Und die XML-RPC-Spec sieht nun auch nicht sooo kompliziert aus :angel:

Nja, mal sehn was ich da hinbekomm.

Elvis 16. Jun 2009 11:23

Re: RPC und Delphi 2009
 
Zitat:

Zitat von alphaflight83
Ab heute gibt es den Real Thin Client (RTC) unter der freien BSD Lizenz.
Hiermit sollte sich dann das leidige Thema RPC auf D2009 vernünftig lösen lassen.

An und für sich mag das ganz gut klingen.
Du solltest aber beachten, dass die RTC Lizenz in diesem Jahr öfter gewechselt wurde als manche Leute ihre Unterwäsche wechseln...

alphaflight83 26. Jun 2009 13:28

Re: RPC und Delphi 2009
 
So, ich hab mich jetzt mal am RTC versucht, was auch im Ansatz funktioniert, solange ich keine Parameter mit senden muss.
Ich habs aber bisher nicht geschnallt, wie ich Parameter richtig übergeben kann.

Delphi-Quellcode:
with RtcHttpClient do begin
  ServerAddr := AnsiString(IP_Address);
  ServerPort := AnsiString(IntToStr(TCP_Port));
  // UseWinHTTP := True;
  Connect;
end;

with RtcClientModule do begin
  ModuleFilename := '/RPC2';
  ModuleHost := AnsiString(IP_Address);
  DataFormat := fmt_XMLRPC;
  StartCalls;
  Data.NewFunction('get_item_descr');
  (* --> hier möchte ich noch die Variable Integer: ItemID als Parameter übergeben *)
  Call(RtcResult);
  Post;
end;

with RtcResult do begin
  if Valid then Result := 1
  else Result := 0;
end;

alphaflight83 29. Jun 2009 10:37

Re: RPC und Delphi 2009
 
Okay, sollte jetzt laufen.

Benutzt wurden:
XMLDocument: TXMLDocument;
RtcHttpClient: TRtcHttpClient;
RtcDataRequest: TRtcDataRequest;

Delphi-Quellcode:
(******************************
** Function: RPC_GetItemDesc **
******************************)
function RPC_GetItemDesc(IP_Address: String; TCP_Port, ItemID: Integer):LongInt;
begin
  with XMLDocument do begin
    Active := true;
    Version := '1.0' ;
    Encoding := 'UTF-8' ;
 
    ChildNodes.Clear;
    with AddChild('methodCall') do begin
      with AddChild('methodName') do
        NodeValue:= 'get_item_descr';
      with AddChild('params') do
        with AddChild('param').AddChild('value').AddChild('int') do
          NodeValue:= ItemID;
    end;
  end;

  with RtcHttpClient do begin
    ServerAddr := AnsiString(IP_Address);
    ServerPort := AnsiString(IntToStr(TCP_Port));
    UseWinHTTP := True;
    Connect;
  end;

  with RtcDataRequest do begin
    Request.Method := 'Post';
    Request.URI := '/RPC2';
    Post;
  end;
end;


(******************************************
** Procedure: RtcDataRequestBeginRequest **
******************************************)
procedure RtcDataRequestBeginRequest(Sender: TRtcConnection);
begin
  with TRtcDataClient(Sender) do begin
    Request['Content-type']:='text/xml';
    Write(AnsiString(XMLDocument.XML.Text));
  end;
end;
Alle anderen Kombinationen die ich ausprobiert hatte, haben mir immer die XML Daten so verbaut,
dass der Server die Anfragen nicht gefressen hat. Mit dieser Kombination tut nun alles wie es soll.

DTkalcec 1. Jul 2009 19:02

Re: RPC und Delphi 2009
 
Hier ist ein Beispiel wie es auch mit der eingebauten XML-RPC funktionalität gehn sollte ...

Benutzt werden:
RtcHttpClient: TRtcHttpClient;
RtcClientModule: TRtcClientModule;
RtcResult: TRtcResult;

Delphi-Quellcode:
with RtcHttpClient do begin
  ServerAddr := AnsiString(IP_Address);
  ServerPort := AnsiString(IntToStr(TCP_Port));
  // UseWinHTTP := True;
  AutoConnect:=True;
end;

with RtcClientModule do begin
  ModuleFilename := '/RPC2';
  ModuleHost := AnsiString(IP_Address);
  DataFormat := fmt_XMLRPC;

  with Data.NewFunction('get_item_descr') do // <methodcall><methodname>
    with newArray('params') do // <params>
      asInteger[0]:=123; // <param><value><int>

  Call(RtcResult); // <- raus damit
end;
Da RTC SDK komponenten event-basierts sind, kommt das resultat in das OnResult event von der RtcResult komponente.

Übrigens ... die "Data.toXMLRPCRequest" funktion kann mann vor dem "Call()" beutzen um zu testen wie das XML-RPC string aussieht das an den Server geschickt wird.

MfG,
Danijel Tkalcec


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:17 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