RPC::pClient(3pm)

πŸ“¦
version 0.1005 Β· 2 versions
  • 0.1005 Β· debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking (latest)
  • 0.1005 Β· ubuntu jammy
, in debian bookworm, debian trixie, ubuntu noble, ubuntu resolute, ubuntu stonking

πŸ’– RPC::pClient β€” the manual, but make it make sense πŸ’–

okay so bestie, welcome to RPC::pClient, a Perl extension for writing pRPC clients ✨. That's the NAME section, and yes, we're doing this whole thing together. Grab a strawberry πŸ“, this is gonna be cute.

This is part of the User Contributed Perl Documentation, and it's giving very much "let me hold your hand through client/server Perl." 🫢


✨ SYNOPSIS ✨

use RPC::pClient;

$sock = IO::Socket::INET->new('PeerAddr' => 'joes.host.de',
                              'PeerPort' => 2570,
                              'Proto' => 'tcp');

$connection = new RPC::pClient('sock' => $sock,
                               'application' => 'My App',
                               'version' => '1.0',
                               'user' => 'joe',
                               'password' => 'hello!');

literally that's it, that's the whole vibe. socket β†’ client object β†’ slay πŸ’…


🌸 DESCRIPTION 🌸

pRPC (Perl RPC) is a package that makes writing Perl-based client/server applications so much easier, no cap. RPC::pServer is the package for the server side, and you can guess what RPC::pClient is for πŸ‘‘. See RPC::pClient(3) for this part.

So here's how pRPC works, bestie: it defines a set of functions that the client may execute πŸ¦‹. For example, the server might offer a function multiply to the client. Now a function call like

@result = $con->Call('multiply', $a, $b);

on the client gets mapped to a corresponding call

multiply($con, $data, $a, $b);

on the server 🌈. (See the funcTable description below for $data.) The function call's result gets returned to the client and stored in the array @result. Simple, eh? :-) iconic behavior fr fr πŸ’–


πŸŽ€ Client methods πŸŽ€

  • new β€” the client constructor πŸ’«. Returns a client object or an error string, so you typically use it like this:
$client = RPC::pClient->new ( ... );
if (!ref($client)) {
    print STDERR "Error while creating client object: $client\n";
} else {
    # Do real stuff
    ...
}

ngl the !ref() check is the whole personality test here: ref = object, not-ref = sad little error string 😭

  • Call β€” calls a function on the server πŸ”₯. The arguments are a function name, followed by function arguments. It returns the function results, if successful. After executing Call() you should always check the error attribute: an empty string means success ✨. So the equivalent to
$c = Add($a, $b)
# Use $c
...

is

$c = $client->Call("Add", $a, $b);
if ($client->error) {
    # Do something in case of error
    ...
} else {
    # Use $c
    ...
}

the way that you must vibe check error every single time… periodt πŸ’…

  • CallInt β€” similar to, and internally used by, Call 🧚. Receives the same arguments, but the result is prepended by a status value: if this status value is TRUE, then all went fine and the following result array is valid βœ…. Otherwise an error occurred and the error message follows immediately after the status code πŸ’€. Example:
my($status, @result) = $client->CallInt("Add", $a, $b);
if (!$status) {
    #  Do something in case of error
    my $errmsg = shift @result  ||  "Unknown error";
    ...
} else {
    ...
}

not the error message just casually sliding in right behind the status code 😭

  • Encrypt β€” this method can be used to get or set the cipher attribute, thus the encryption mode πŸ”. If the method is passed an argument, the argument will be used as the new encryption mode. (undef for no encryption.) In either case the current encryption mode will be returned ✨. Example:
# Get the current encryption mode
$mode = $server->Encrypt();

# Currently disable encryption
$server->Encrypt(undef);

# Switch back to the old mode
$server->Encrypt($mode);

getter AND setter in one method? she's flexible, she contains multitudes πŸ’œ


πŸ¦‹ Client attributes πŸ¦‹

Client attributes will typically be supplied with the new constructor.

  • sock β€” an object of type IO::Socket, which should be connected to the server πŸ”Œ.
  • cipher β€” this attribute can be used to add encryption quite easily πŸ”. pRPC is not bound to a certain encryption method, but to a block encryption API. The attribute is an object supporting the methods blocksize, encrypt and decrypt. For example, the modules Crypt::DES and Crypt::IDEA support such an interface ✨.

Note that you can set or remove encryption on the fly (putting undef as attribute value will stop encryption), but you have to be sure that both sides change the encryption mode ⚠️.

🚨 Do not modify this attribute directly, use the encrypt method instead! However, it is legal to pass the attribute to the constructor.

Example:

use Crypt::DES;
$crypt = DES->new(pack("H*", "0123456789abcdef"));
$client->Encrypt($crypt);

# or, to stop encryption
$client->Encrypt(undef);
  • application
  • version
  • user
  • password β€” it is part of the pRPC authorization process that the client must obeye a login procedure where he will pass an application name, a protocol version and optionally a user name and password πŸ”‘. You do not care for that (except passing the right values, of course :-), this is done within the client constructor 🫢.
  • io β€” this attribute is the Storable object created for communication with the server πŸ’Œ. You may use this, for example, when you want to change the encryption mode with Storable::Encrypt(). See Storable(3) 🌈.

πŸ”₯ EXAMPLE πŸ”₯

here's the whole thing, ready to run, no notes:

#!/usr/local/bin/perl -T
use 5.0004;               # Yes, this really *is* required.
use strict;               # Always a good choice.

use IO::Socket();
use RPC::pClient;

# Constants
my $MY_APPLICATION = "Test Application";
my $MY_VERSION = 1.0;
my $MY_USER = "foo";
my $MY_PASSWORD = "bar";

# Connect to the server
my $sock = IO::Socket::INET->new('PeerAddr' => 'joes.host.de',
                                 'PeerPort' => 5000,
                                 'Proto' => 'tcp');
if (!defined($sock)) {
    die "Cannot connect: $!\n";
}

# Login procedure
my $client = RPC::pClient->new('sock' => $sock,
                               'application' => $MY_APPLICATION,
                               'version' => $MY_VERSION,
                               'user' => $MY_USER,
                               'password' => $MY_PASSWORD);
if (!ref($client)) {
    die "Cannot create client: $client\n";
}

# Call multiply function
my $a = $client->Call("multiply", 3, 4);
if ($client->error) {
    die "An error occurred while multiplying: $a\n";
}

bestie the comments in this example are lowkey iconic β€” # Yes, this really *is* required. and # Always a good choice. β€” she knew πŸ˜­πŸ’…


πŸ‘‘ AUTHOR πŸ‘‘

Jochen Wiedmann, wiedmann@neckar-alb.de β€” thank you for your service, king πŸ«‘πŸ’œ


🌈 SEE ALSO 🌈

  • pRPC::Server(3)
  • Storable(3)
  • Sys::Syslog(3)

For an example application, see DBD::pNET(3) πŸ¦‹βœ¨


and that's the whole page, bestie!! this one shipped with perl v5.36.0 and is dated 2022-12-04 β€” so go forth, connect your sockets, check your error attribute, and slay πŸ’…πŸŽ€πŸ’–

πŸ“¦ where this page comes from