<?xml version="1.0" encoding="UTF-8"?>
<!-- EN-Revision: 17178 -->
<!-- Reviewed: no -->
<sect1 id="zend.xmlrpc.client">
    <title>Zend_XmlRpc_Client</title>

    <sect2 id="zend.xmlrpc.client.introduction">
        <title>Einführung</title>

        <para>
            Zend Framework bietet Unterstützung, als Client - durch das
            <classname>Zend_XmlRpc_Client</classname> Paket - entfernte <acronym>XML-RPC</acronym>
            Dienste zu nutzen. Seine wichtigsten Möglichkeiten beinhalten das automatische
            Umwandeln zwischen <acronym>PHP</acronym> und <acronym>XML-RPC</acronym>, ein Server
            Proxy-Objekt und den Zugriff auf Server-Prüfungsmöglichkeiten.
        </para>

    </sect2>

    <sect2 id="zend.xmlrpc.client.method-calls">
        <title>Methodenaufrufe</title>

        <para>
            Der Konstruktor von <classname>Zend_XmlRpc_Client</classname> erhält den
            <acronym>URL</acronym> des Endpunktes des entfernten <acronym>XML-RPC</acronym> Server
            als ersten Parameter. Die zurückgegebene Instanz kann genutzt werden, um eine beliebige
            Anzahl von entfernten Methoden (des Endpunktes) aufzurufen.
        </para>

        <para>
            Um eine entfernte Methode mittels des <acronym>XML-RPC</acronym> Clients aufzurufen,
            muss man den Client instanzieren und dessen Methode <methodname>call()</methodname>
            aufrufen. Das hierunter gegebene Codebeispiel demonstriert den
            <acronym>XML-RPC</acronym> Server der Zend Framework Webseite. Es kann benutzen, um
            <classname>Zend_XmlRpc</classname>-Komponenten zu testen oder auszuprobieren.
        </para>

        <example id="zend.xmlrpc.client.method-calls.example-1">
            <title>XML-RPC Methodenaufruf</title>
            <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

echo $client->call('test.sayHello');

// hello
]]></programlisting>
        </example>

        <para>
            Der - durch den Aufruf einer entfernten Methode - zurückgegebene, typenlose
            <acronym>XML-RPC</acronym> Wert wird automatisch zu dessen nativen
            <acronym>PHP</acronym> Äquivalent umgeformt. In obigem Beispiel wird ein
            <acronym>PHP</acronym> <type>String</type> zurückgegeben und ist sofort benutzbar.
        </para>

        <para>
            Der erste Parameter the Methode <methodname>call()</methodname> ist der Name der
            aufzurufenden Methode. Wenn die entfernte Methode weitere Parameter
            benötigt, können diese durch einen zweiten, optionalen Parameter des Typs
            <type>Array</type> an <methodname>call()</methodname> angegeben werden, wie folgendes
            Beispiel zeigt:
        </para>

        <example id="zend.xmlrpc.client.method-calls.example-2">
            <title>XML-RPC Methodenaufruf mit Parametern</title>
            <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$arg1 = 1.1;
$arg2 = 'foo';

$result = $client->call('test.sayHello', array($arg1, $arg2));

// $result ist ein nativer PHP-Typ
]]></programlisting>
        </example>

        <para>
            Wenn die entfernte Methode keine Parameter erwartet, kann der
            optionale Parameter weggelassen oder stattdessen ein leeres
            <methodname>array()</methodname> übergeben werden. Das, die Parameter -
            für die entfernte Methode - enthaltende, Array kann native
            <acronym>PHP</acronym> Typen, <classname>Zend_XmlRpc_Value</classname>-Objekte oder
            eine Mischung aus Beidem enthalten.
        </para>

        <para>
            Die <methodname>call()</methodname>-Methode konvertiert automatisch die
            <acronym>XML-RPC</acronym> Antwort in dessen äquivalenten nativen
            <acronym>PHP</acronym> Typen und gibt sie zurück. Ein
            <classname>Zend_XmlRpc_Response</classname> Objekt als Rückgabewert ist auch verfübar
            durch das Aufrufen der Methode <methodname>getLastResponse()</methodname> nach dem
            Aufruf (der entfernten Methode).
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.value.parameters">
        <title>Typen und Konvertierung</title>
        <para>
            Einige entfernte Methodenaufrufe benötigen Parameter. Diese werden
            an die Methode <methodname>call()</methodname> des
            <classname>Zend_XmlRpc_Client</classname>s als Array im zweiten Parameter übergeben.
            Jeder Parameter kann entweder ein nativer <acronym>PHP</acronym> Typ sein, der
            automatisch konvertiert wird, oder ein Objekt, das einem speziellen
            <acronym>XML-RPC</acronym> Typen (eines der
            <classname>Zend_XmlRpc_Value</classname>-Objekte) entspricht.
        </para>

        <sect3 id="zend.xmlrpc.value.parameters.php-native">
            <title>Native PHP-Typen als Parameter</title>
            <para>
                Parameter können der Methode <methodname>call()</methodname> als native
                <acronym>PHP</acronym> Variablen übergeben werden, also als <type>String</type>,
                <code>integer</code>, <code>float</code>,
                <type>Boolean</type>, <type>Array</type> oder als ein
                <code>Objekt</code>. In diesem Fall wird jeder native <acronym>PHP</acronym> Typ
                automatisch erkannt und dann in einen der folgenden <acronym>XML-RPC</acronym>
                Typen konvertiert, welche in dieser Tabelle ersichtlich ist:
            </para>

            <table id="zend.xmlrpc.value.parameters.php-native.table-1">
                <title>PHP- und XML-RPC-Typkonvertierungen</title>
                <tgroup cols="2">
                    <thead>
                        <row>
                            <entry>Nativer <acronym>PHP</acronym> Typ</entry>
                            <entry><acronym>XML-RPC</acronym> Typ</entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry>integer</entry>
                            <entry>int</entry>
                        </row>
                        <row>
                            <entry>double</entry>
                            <entry>double</entry>
                        </row>
                        <row>
                            <entry>boolean</entry>
                            <entry>boolean</entry>
                        </row>
                        <row>
                            <entry>string</entry>
                            <entry>string</entry>
                        </row>
                        <row>
                            <entry>array</entry>
                            <entry>array</entry>
                        </row>
                        <row>
                            <entry>associative array</entry>
                            <entry>struct</entry>
                        </row>
                        <row>
                            <entry>object</entry>
                            <entry>array</entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>

            <note>
                <title>Auf welchen Typ werden leere Arrays gecastet?</title>

                <para>
                    Die Übergabe eines leeren Array an eine <acronym>XML-RPC</acronym> Methode ist
                    problematisch, da es entweder ein Array oder ein Struct repräsentieren könnte.
                    <classname>Zend_XmlRpc_Client</classname> erkennt solche Konditionen und führt
                    eine Abfrage zur <code>system.methodSignature</code> Methode des Servers aus,
                    um den richtigen <acronym>XML-RPC</acronym> Typ festzustellen auf den gecastet
                    werden soll.
                </para>

                <para>
                    Trotzdem kann das selbst sogar zu Problemen führen. Erstens werden Server die
                    <code>system.methodSignature</code> nicht unterstützen fehlerhafte Anfragen
                    protokollieren, und <classname>Zend_XmlRpc_Client</classname> wird selbst einen
                    Ausweg nehmen und den Wert auf ein Array casten. Zusätzlich bedeutet das das
                    jeder Aufruf mit einem Array Argument zu einem zusätzlichen Aufruf beim Remote
                    Server führt.
                </para>

                <para>
                    Um das Nachsehen komplett abzuschalten kann die
                    <methodname>setSkipSystemLookup()</methodname> Methode aufgerufen werden bevor
                    der <acronym>XML-RPC</acronym> Aufruf durchgeführt wird:
                </para>

                <programlisting language="php"><![CDATA[
$client->setSkipSystemLookup(true);
$result = $client->call('foo.bar', array(array()));
]]></programlisting>
            </note>
        </sect3>

        <sect3 id="zend.xmlrpc.value.parameters.xmlrpc-value">
            <title>Zend_XmlRpc_Value-Objekte als Parameter</title>
            <para>
                Parameter können auch direkt als <classname>Zend_XmlRpc_Value</classname>-Instanzen
                erstellt werden, um einen exakten <acronym>XML-RPC</acronym> Typen darzustellen.
                Die wichtigsten Gründe dafür sind:

                <itemizedlist>
                    <listitem>
                        <para>
                            Wenn sichergestellt werden soll, dass der Prozedur der
                            korrekte Parametertyp übergeben wird (z.B. braucht die
                            Prozedur einen integer, während diese vielleicht
                            von einer Datenbank als String zurückgegeben wird).
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Wenn die Prozedur einen <code>base64</code>- oder einen
                            <code>dateTime.iso8601</code>-Typ benötigt, da diese
                            nicht als native <acronym>PHP</acronym> Typen existieren.
                        </para>
                    </listitem>
                    <listitem>
                        <para>
                            Wenn eine automatische Konvertierung fehlschlägt. Zum Beispiel wenn
                            eine leere <acronym>XML-RPC</acronym> Struktur als Parameter für die
                            Prozedur gewünscht ist. Leere Strukturen werden jedoch als leere Arrays
                            in <acronym>PHP</acronym> gehandhabt, aber wenn man ein leeres Array
                            als Parameter übergeben will, dann wird es automatisch zu einem
                            <acronym>XML-RPC</acronym> Array konvertiert, da es kein assoziatives
                            Array ist.
                        </para>
                    </listitem>
                </itemizedlist>
            </para>

            <para>
                Es gibt zwei Möglichkeiten ein <classname>Zend_XmlRpc_Value</classname>-Objekt
                zu erstellen: Direkte Instanzierung einer
                <classname>Zend_XmlRpc_Value</classname>-Subklasse oder das Nutzen der statischen
                Fabrikmethode <methodname>Zend_XmlRpc_Value::getXmlRpcValue()</methodname>.
            </para>

            <table id="zend.xmlrpc.value.parameters.xmlrpc-value.table-1">
                <title>Zend_XmlRpc_Value Objekte als XML-RPC Typen</title>
                <tgroup cols="3">
                    <thead>
                        <row>
                            <entry><acronym>XML-RPC</acronym> Typ</entry>
                            <entry><classname>Zend_XmlRpc_Value</classname> Konstante</entry>
                            <entry><classname>Zend_XmlRpc_Value</classname> Objekt</entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry>int</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_INTEGER</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_Integer</classname></entry>
                        </row>
                        <row>
                            <entry>double</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_DOUBLE</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_Double</classname></entry>
                        </row>
                        <row>
                            <entry>boolean</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_BOOLEAN</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_Boolean</classname></entry>
                        </row>
                        <row>
                            <entry>string</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_STRING</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_String</classname></entry>
                        </row>
                        <row>
                            <entry>base64</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_BASE64</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_Base64</classname></entry>
                        </row>
                        <row>
                            <entry>dateTime.iso8601</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_DateTime</classname></entry>
                        </row>
                        <row>
                            <entry>array</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_ARRAY</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_Array</classname></entry>
                        </row>
                        <row>
                            <entry>struct</entry>
                            <entry>
                                <constant>Zend_XmlRpc_Value::XMLRPC_TYPE_STRUCT</constant>
                            </entry>
                            <entry><classname>Zend_XmlRpc_Value_Struct</classname></entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>

            <para>
                <note>
                    <title>Automatische Konvertierung</title>
                    <para>
                        Bei der Erstellung eines neuen
                        <classname>Zend_XmlRpc_Value</classname>-Objekts wird dessen Wert durch
                        einen nativen <acronym>PHP</acronym> Typ gesetzt. Dieser
                        <acronym>PHP</acronym> Typ wird durch <acronym>PHP</acronym> Casting in den
                        gewünschten Typ umgewandelt. Beispielsweise wird ein String, der als Wert
                        für ein <classname>Zend_XmlRpc_Value_Integer</classname>-Objekt genutzt
                        wird, durch <code>(int)$value</code> in ein Integer konvertiert.
                    </para>
                </note>
            </para>
        </sect3>
    </sect2>

    <sect2 id="zend.xmlrpc.client.requests-and-responses">
        <title>Server-Proxy-Objekt</title>
        <para>
            Ein anderer Weg um entfernte Methoden mit <acronym>XML-RPC</acronym> Clients
            aufzurufen, ist die Verwendung eines Server-Proxys. Dies ist ein
            <acronym>PHP</acronym> Objekt, das einen entfernten <acronym>XML-RPC</acronym>
            Namensraum umleitet, sodass es so weit wie möglich als <acronym>PHP</acronym> Objekt
            arbeitet wie es möglich ist.
        </para>

        <para>
            Um einen Server-Proxy zu instanzieren, muss die Methode
            <methodname>getProxy()</methodname> der Klasse <classname>Zend_XmlRpc_Client</classname>
            aufgerufen werden. Das retourniert eine Instanz von
            <classname>Zend_XmlRpc_Client_ServerProxy</classname>. Jeder Methodenaufruf
            wird zur entsprechenden entfernten Methode weitergeleitet. Die Parameter
            können übergeben werden, wie bei jeder anderen <acronym>PHP</acronym> Methode.
        </para>

        <example id="zend.xmlrpc.client.requests-and-responses.example-1">
            <title>Umleitung zum Standard-Namenraum</title>
            <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$server = $client->getProxy();           // Umleitung im Standard-Namenraum

$hello = $server->test->sayHello(1, 2);  // test.Hello(1, 2) gibt "hello" zurück
]]></programlisting>
        </example>

        <para>
            Die Methode <methodname>getProxy()</methodname> erhält ein optionales Argument,
            welches den Namensraum des entfernten Servers definiert, zu welchem
            die Methodenaufrufe umgeleitet werden. Wenn kein Namensraum übergeben
            wird, wird zum Standard-Namensraum umgeleitet. Im nächsten Beispiel
            wird zum <code>test</code>-Namensraum umgeleitet:
        </para>

        <example id="zend.xmlrpc.client.requests-and-responses.example-2">
            <title>Umleitung zu einem beliebigen Namensraum</title>
            <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$test  = $client->getProxy('test');     // Leitet zum "test"-Namensraum um

$hello = $test->sayHello(1, 2);         // test.Hello(1,2) gibt "hello" zurück
]]></programlisting>
        </example>

        <para>
            Wenn der entfernte Server verschachtelte Namensräume jeglicher
            Tiefe erlaubt, können diese auch durch den Server-Proxy genutzt
            werden. Wenn der Server in obigem Beispiel eine Methode
            <methodname>test.foo.bar()</methodname> hätte, könnte es durch
            <code>$test->foo->bar()</code> aufgerufen werden.
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.client.error-handling">
        <title>Fehlerbehandlung</title>
        <para>
            Es gibt zwei Arten von Fehlern, die während eines <acronym>XML-RPC</acronym>
            Methodenaufruf autreten können: <acronym>HTTP</acronym> und <acronym>XML-RPC</acronym>
            Fehler. Der <classname>Zend_XmlRpc_Client</classname> erkennt beide und ermöglicht es,
            diese unabhängig voneinander zu entdecken und abzufangen.
        </para>

        <sect3 id="zend.xmlrpc.client.error-handling.http">
            <title>HTTP-Fehler</title>

            <para>
                Wenn ein <acronym>HTTP</acronym> Fehler auftritt, wie z.B. wenn der entfernte
                <acronym>HTTP</acronym> Server einen <code>404 Not Found</code> zurückgibt, wird
                eine <classname>Zend_XmlRpc_Client_HttpException</classname> geworfen.
            </para>

            <example id="zend.xmlrpc.client.error-handling.http.example-1">
                <title>Verarbeiten von HTTP-Fehlern</title>

                <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://foo/404');

try {

    $client->call('bar', array($arg1, $arg2));

} catch (Zend_XmlRpc_Client_HttpException $e) {

    // $e->getCode() gibt 404 zurück
    // $e->getMessage() gibt "Not Found" zurück

}
]]></programlisting>
            </example>

            <para>
                Ungeachtet des benutzten <acronym>XML-RPC</acronym> Clients wird immer eine
                <classname>Zend_XmlRpc_Client_HttpException</classname> geworfen, wenn
                ein <acronym>HTTP</acronym> Fehler auftritt.
            </para>
        </sect3>

        <sect3 id="zend.xmlrpc.client.error-handling.faults">
            <title>XML-RPC-Fehler</title>

            <para>
                Ein <acronym>XML-RPC</acronym> Fehler wird analog zu einer <acronym>PHP</acronym>
                Exception verwendet. Es ist ein spezieller Typ, der durch einen
                <acronym>XML-RPC</acronym> Methodenaufruf zurückgegeben wurden und einen Fehlercode
                sowie eine Fehlermeldung enthält. <acronym>XML-RPC</acronym> Fehler werden
                unterschiedlich behandelt, was von der Benutzung des
                <classname>Zend_XmlRpc_Client</classname>s abhängt.
            </para>

            <para>
                Wenn die Methode <methodname>call()</methodname> oder der Server-Proxy genutzt
                wird, würde durch einen <acronym>XML-RPC</acronym> Fehler eine
                <classname>Zend_XmlRpc_Client_FaultException</classname> geworfen werden. Der
                Fehlercode und die -meldung der Exception zeigen auf deren zugehörige
                Werte in der originalen <acronym>XML-RPC</acronym> Fehlerantwort.
            </para>

            <example id="zend.xmlrpc.client.error-handling.faults.example-1">
                <title>Verarbeiten von XML-RPC Fehlern</title>

                <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

try {

    $client->call('badMethod');

} catch (Zend_XmlRpc_Client_FaultException $e) {

    // $e->getCode() gibt 1 zurück
    // $e->getMessage() gibt "Unknown method" zurück

}
]]></programlisting>
            </example>

            <para>
                Wenn die Methode <methodname>call()</methodname> genutzt wird, um eine Anfrage zu
                starten, wird die <classname>Zend_XmlRpc_Client_FaultException</classname> bei einem
                Fehler geworfen. Ein <classname>Zend_XmlRpc_Response</classname>-Objekt, das den
                Fehler enthält, ist allerdings auch verfübar durch die Methode
                <methodname>getLastResponse()</methodname>.
            </para>

            <para>
                Wenn die Methode <methodname>doRequest()</methodname> genutzt wird, um eine
                Anfrage zu starten, wird keine Exception geworfen. Stattdessen
                wird ein <classname>Zend_XmlRpc_Response</classname>-Objekt zurückgegeben,
                das den Fehler enthält. Dieses kann durch den Aufruf der Methode
                <methodname>isFault()</methodname> der Klasse
                <classname>Zend_XmlRpc_Response</classname> überprüft werden.
            </para>
        </sect3>

    </sect2>

    <sect2 id="zend.xmlrpc.client.introspection">
        <title>Server Selbstüberprüfung</title>
        <para>
            Einige <acronym>XML-RPC</acronym> Server bieten de facto Überprüfungsmethoden unter dem
            <acronym>XML-RPC</acronym> Namesraum <code>system.</code>.
            <classname>Zend_XmlRpc_Client</classname> stellt spezielle Verfahren für Server mit
            diesen Möglichkeiten zur Verfügung.
        </para>

        <para>
            Eine Instanz der Klasse <classname>Zend_XmlRpc_Client_ServerIntrospection</classname>
            kann über die Methode <methodname>getIntrospector()</methodname> der Klasse
            <classname>Zend_XmlRpcClient</classname> zurückgegeben werden. Sie kann dann genutzt
            werden, um Überwachungsoperationen auf dem Server auszuführen.
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.client.request-to-response">
        <title>Von der Anfrage zur Antwort</title>
        <para>
            Intern erstellt die Methode <methodname>call()</methodname> des
            <classname>Zend_XmlRpc_Client</classname>-Objekts ein Anfrage-Objekt
            (<classname>Zend_XmlRpc_Request</classname>) und sendet es zu einer anderen
            Methode, <methodname>doRequest()</methodname>, die ein Antwort-Objekt
            (<classname>Zend_XmlRpc_Response</classname>) zurückgibt.
        </para>

        <para>
            Die Methode <methodname>doRequest()</methodname> kann auch direkt genutzt werden:
        </para>

        <example id="zend.xmlrpc.client.request-to-response.example-1">
            <title>Eine Anfrage zu einer Antwort verarbeiten</title>

            <programlisting language="php"><![CDATA[
$client = new Zend_XmlRpc_Client('http://framework.zend.com/xmlrpc');

$request = new Zend_XmlRpc_Request();
$request->setMethod('test.sayHello');
$request->setParams(array('foo', 'bar'));

$client->doRequest($request);

// $server->getLastRequest() gibt ein Zend_XmlRpc_Request-Objekt zurück
// $server->getLastResponse() gibt ein Zend_XmlRpc_Response-Objekt zurück
]]></programlisting>
        </example>

        <para>
            Immer wenn eine <acronym>XML-RPC</acronym> Methode vom Client aufgerufen wird,
            egal auf welche Weise - entweder über die Methode <methodname>call()</methodname>,
            die Methode <methodname>doRequest()</methodname> oder den Server-Proxy -, ist das
            Objekt der letzten Anfrage, sowie dessen resultierende Antwort-Objekte,
            immer durch die Methoden <methodname>getLastRequest()</methodname> und
            <methodname>getLastResponse()</methodname> verfügbar.
        </para>
    </sect2>

    <sect2 id="zend.xmlrpc.client.http-client">
        <title>HTTP-Client und das Testen</title>

        <para>
            In jedem der vorangegangenen Beispiele wurde kein <acronym>HTTP</acronym> Client
            bestimmt. In diesem Fall wird eine neue Instanz eines
            <classname>Zend_Http_Client</classname>s mit dessen standardmäßigen
            Einstellungen erstellt und automatisch vom <classname>Zend_XmlRpc_Client</classname>
            benutzt.
        </para>

        <para>
            Der <acronym>HTTP</acronym> Client kann zu jeder Zeit mit der Methode
            <methodname>getHttpClient()</methodname> zurückgegeben werden. In den meisten
            Fällen jedoch ist der Standard <acronym>HTTP</acronym> Client ausreichend. Allerdings
            erlaubt die Methode <methodname>setHttpClient()</methodname> das Setzen eines
            anderen <acronym>HTTP</acronym> Clients.
        </para>

        <para>
            Die Methode <methodname>setHttpClient()</methodname> ist besonders nützlich für
            UnitTests. Wenn es mit dem <classname>Zend_Http_Client_Adapter_Test</classname>
            kombiniert wird, können entfernte Services für das Testen nachgeahmt werden.
            In den UnitTests für <classname>Zend_XmlRpc_Client</classname> sind Beispiele,
            wie so was erreicht werden kann.
        </para>
    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->