3
Tags:
php
Skrevet af
Bruger #4304
@ 25.01.2005
Indledning
Web services er kort fortalt, en måde at afvikle funktioner som andre har skrevet over nettet. XML-RPC[1] er en gammel måde at gøre dette på, den stammer helt tilbage fra 1998 hvor Userland Software[2] udviklede teknologien. Men web services er først blevet "rigtig " populære efter .NET kom på markedes, som gør stor brug af SOAP (ret mig hvis jeg tager fejl, men skulle mene de bruger SOAP).
Nu er os PHP programmøre midlertidigt så heldige, at der er nogen flinke folk som har lavet som har lavet en extension[3] til PHP. Denne extension er bygget over en API[4] til C. Udover denne extension, er der også lavet en lille klasse[5] til at hjælpe, når man laver XML-RPC server og klienter med PHP. Denne artikel, vil dog undlade at bruge denne klasse, og lave sin egen lille funktion som kan kalde og gøre ved.
Kort fortalt så virker XMl-RPC på den måde, at klienten kalder en server via port 80 (hvilket gør at det størstedelen af tiden går forbi diverse firewalls). Det klienten sender er et XML dokument, med information om hvilken funktioner der skal kaldes, med hvilken argumenter. Når serveren får denne XML, kalder den så denne funktion (suprise suprise), og sender så en XML streng tilbage til klienten. Denne indeholder så det funktionen har returneret (samt en hvilken type det er, så klienten ved om det er en streng, array, integer, etc.).
-- Bemærk: At du skal installere XML-RPC først, læs hvordan i PHP manualen[6]. Hvis du efter at havde kigget i PHP manualen stadig ikke kan hitte ud af, at få XML-RPC installeret... Ja så er du på den, da dette er krævet før nedenstående vil virkeps. det kan være en god ide, at kopiere koden hen i din favorit php editor, da der kommer syntax farve på(formentlig), og det gør det nemmere at skelne kommentar fra kode.
Server delen
Tja vi starter med serveren, da vores klient af gode grunde ikke virker uden en server. Men det nemmeste ville væl være at komme med et fint lille eksempel(som jeg har kommenteret til min bedste kunnen).
xmlrpc_server.php
/****
* Lad os starte med at lave de funktioner,
* som serveren vil kunne svare klienten med.
* Disse funktioner skal havde 3 parameter, som
* XML-RPC bruger, når der bliver kaldt en funktion.
* Disse parameter er som følgende:
* 1) Navnet på den funktion, der bliver kaldt.
* 2) Et array, som indeholder de parametre, som
* klienten har indtastet i funktions kaldet.
* 3) Den sidste kan være en hvilken som helst
* data, serveren har specificeret.
****/
function xmlEcho($method_name, $params, $app_data)
{
// Returnere bare hvad brugeren skriver
// i som parameteren
return 'echo: '. $params[0];
}
function xmlAllToUpper($method_name, $params, $app_data)
{
// Returnere parameteren som store bogstaver
for ($i = 0; $i < count($params); $i++) {
$params[$i] = strToUpper($params[$i])
}
return $params;
}
/****
* Nu laver vi et handle, til serveren. Dette
* sætter vi til $xmlServer.
****/
$xmlServer = xmlrpc_server_create();
/****
* Nu registrere vi vores funktioner skrevet ovenfor.
* Dette gøres med xmlrpc_server_register_method.
* Denne funktion tager 3 argumenter:
* 1) Et server handle.
* 2) Hvad klienten skal kalde, for at kalde funktionen.
* 3) Hvilken funktion serveren skal kalde.
****/
xmlrpc_server_register_method($xmlServer, "echo", "xmlEcho");
xmlrpc_server_register_method($xmlServer, "GoLarge",
"xmlAllToUpperService");
/****
* Når klienten kalder vores server, sendes en
* forespørgsel med, det er denne som kalder en
* funktion. Denne forspørgsel kan hentes på
* følgende måde
****/
$xmlRequest = $HTTP_RAW_POST_DATA;
/****
* Efter vi har modtaget vores $xmlRequest,
* skal serveren lige sættes i gang, dette gøres
* med funktioen: xmlrpc_server_call_method.
* Og ganske som det plejer, har vi 3 argumenter:
* 1) Server handle
* 2) Vores forspørgsel ($xmlRequest)
* 3) Data, som bestemmes af serveren. Den der
* $app_data oppe i vores funktioner.
****/
$xmlOutput = xmlrpc_server_call_method($xmlServer, $xmlRequest, NULL);
/****
* For klienten kan læse hvad funktionen returnere,
* skal denne selvfølgelig skrives:
****/
echo $xmlOutput
/****
* Her stopper vi vores server handle. Jeg er
* lidt i tvivl om denne lukkes automatisk, eller
* om den er persistent.
****/
xmlrpc_server_destroy($xmlServer);
Puha, ja det var så serverdelen, nu kommer vi til klientdelen:
Klienten
Hvis du ikke har arbejdet med sockets[7] før, skal du holde tungen lige i munden. Men bliv nu ikke bange, det er ikke en artikkel om netværks programmering, og jeg vil derfor ikke gå nærmere ind i det (eller HTTP kaldet som også kommer nedenfor). Nu hvor jeg er færdig med at skræmme livet af jer alle sammen, med farlig farlig netværks programming, tror jeg bare vi smutter direkte videre til koden.
xmlrpc_client.php
/****
* Det første vi gør, er at lave en funktion, der
* kan kalde vores server, og returnere et svar.
* Dette gøres som sagt ved sockets, men hvis
* du kender bare lidt til socket eller HTTP, burde
* det ikke være noget problem at forstå.
****/
function sendRequest($host, $url, $request, $port = 80)
{
// Først åbner vi en forbindelse til serveren.
if ( !$sock = fsockopen($host, $port, $errNo, $errString) ) {
echo 'Error: '. $errNo . ' - '. $errString;
return false;
}
// Nu laver vi vores request. Læg mærke til det
// er en hel normal POST HTTP header, der sætter
// content-type til XML.
$httpQuery = "POST ". $url ." HTTP/1.0\\n";
$httpQuery .= "Host: ". $host ."\\n";
$httpQuery .= "Content-Type: text/xml\\n";
$httpQuery .= "Content-Length: ". strlen($request) ."\\n\\n";
$httpQuery .= $request ."\\n";
// Nu sendes forspørgslen
if ( !fwrite($sock, $httpQuery, strlen($httpQuery)) ) {
echo 'Error while trying to send request';
return false;
}
// Serverens svar hentes
while (!feof($sock)) {
$response .= fgets($sock);
}
// Vores handle lukkes
fclose($sock);
// Her fjerner vi den HTTP header som serveren har sendt med
$response = substr($response, strpos($response, "\\r\\n\\r\\n") +4);
// Resultatet bliver dekodet til hvad der nu er blevet sendt.
$response = xmlrpc_decode($response);
// Og vi returnere resultatet.
return $response;
}
/****
* Nu skal vi havde pakket vores forspørgsel ned
* det bruges xmlrpc_encode_request til. Det den gør
* er meget simpelt at pakke det hele ind i et XML
* godkendt format, som XML-RPC bruger.
* Den modtager 2 argumenter:
* 1) Den funktion man gerne vil kalde.
* 2) De argumenter man vil sende.
****/
$xmlRequest = xmlrpc_encode_request('echo', NULL);
// Vi sender vores forspørgsel, og viser det på skærmen:
var_dump(sendRequest('127.0.0.1', '/xml_server.php', $xmlRequest));
Det var jo ualmindelig simpelt. Læg mærke til, at jeg sender
NULL med som parameter, dette er nødvendigt, da 2. parameter i
xmlrpc_encode_request ikek er frivilig. Det ville være muligt at sende alt muligt andet, men man risikere at funktionen man kalder fortolker det forkert, hvis der f.eks. er en sætning der ser således ud i server funktionen:
if ( isset($params[0]) ) {
// [...]
}
Hvis man i ovenstående tilfælde havde brugt
'' i stedet for
NULL, ville koden blive kørt.
Lad os prøve at flere parametre med. Dette gøres ved at sende dem som et array:
$xmlRequest = xmlrpc_encode_request('GoLarge',
array('big', 'tiny', 'large'));
// Vi sender vores forspørgsel, og viser det på skærmen:
var_dump(sendRequest('127.0.0.1', '/xml_server.php', $xmlRequest));
De 3 parametre skulle gerne være blevet til store bogstaver allesammen.
Konklusion
Blandt de 3-4 kendte måder at lave en webservice på, må man jo sige at XML-RPC er helt fin. Det har været på banen snart nogen år, og er derfor godt gennemtestet. Men som med alt andet, er det jo en smagssag, hvad man bedst kan lide at arbejde med, min personlige favorit er XML-RPC (derfor artiklen blev om denne metode).
Prøv evt. nogen af de gratis webservices du kan finde her:
http://xmlrpc.scripting.com/directory/1568/servicesFor at leje lidt rundt med XML-RPC.
Kilder
[1] XML-RPC Info:
http://www.xmlrpc.com/[2] Userland:
http://www.userland.com[3] PHP Manual:
http://www.php.net/manual/en/ref.xmlrpc.php[4] XML-RPC API til C:
http://xmlrpc-epi.sourceforge.net/[5] Hjælpe klasse:
http://xmlrpc.usefulinc.com/php.html[6] PHP Install:
http://dk.php.net/install[7] fsockopen:
http://dk.php.net/manual/en/function.fsockopen.php
Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.
Del også gerne artiklen med dine Facebook venner:
Kommentarer (6)
Jeg har også skrevet denne artikkel på engelsk:
http://birk-jensen.dk/psc/xmlrpc.htmDen engelske version indeholder lidt(meget lidt) teori omkring XML-RPC, samt lidt ekstra af diverse.
Jeg synes det er en udemærket artikel, har bare ingen ide om hvad jeg kan bruge det til. Synes der mangler et kort beskrevet praktisk eksempel, ligesom når man lærer noget i matematik, så får man lige et teknisk eksempel på hvor man kan bruge det. Det ville have været et stort plus. 3 herfra.
hmm, et praktisk eksempel... Amazon har f.eks. en web service (ikke XML-RPC, men SOAP mener jeg), som man kan kalde, og få information omkring en bog. Her kan man så få alt den information der står på deres hjemmeside. Det er her en hel del nemmere at skaffe sig denne information via en webservice end at "skrappe" siden for info via normal HTTP forbindelse.
Jeg må indrømme at jeg ikke helt forstod formålet. Derudover kunne jeg godt bruge din definition på en web service... tak
når i skriver vejledninger så undlad de overflødige ting som fx "stammer helt tilbage fra 1998" det glæmmr de fleste aligevæl, og jeg har det næsten aldtid sådan når jeg ser den slaks (kom nu til sagen) det tager i de værste tilfælde dobelt så lang tid at læse sig igenem en bog eller vejledning på netet.
Jeg stod faktisk og ledte efter en PHP net service, sjovt nok, da jeg gik ind under PHP herinde uden at forvente at finde noget og voila... Her kom du med en artikkel om emnet...
Takker!
Og til jer andre, så hvad angår webservices HAR jeg prøvet at strippe HTML / CSS / RSS med .NET og det er ikke særligt sjovt... Så hellere udnytte PHP's styrke og smide det sammen med noget letforståeligt .NET client system
Du skal være
logget ind for at skrive en kommentar.