Implementing a Simple RPC Framework in PHP Using Sockets
This article explains the concept of Remote Procedure Call (RPC), demonstrates how to build a lightweight PHP RPC server and client with socket programming, shows the full source code, execution steps, and explains the custom protocol used for cross‑language method invocation.
RPC (Remote Procedure Call) enables a program on one system to invoke methods on a program running on another system, such as a PHP application calling a Java service. Since direct calls are impossible across different runtimes, a custom protocol over TCP sockets is used.
The example creates a PHP socket server (RpcServer.php) that listens for incoming connections, parses a simple text protocol containing the target class, method, and optional JSON‑encoded parameters, loads the corresponding class file, instantiates the class, invokes the requested method, and returns the result to the client.
Server implementation (simplified):
<?php
class RpcServer {
protected $serv = null;
public function __construct($host, $port, $path) {
$this->serv = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr);
if (!$this->serv) exit("{$errno} : {$errstr}\n");
$realPath = realpath(__DIR__ . $path);
if ($realPath === false || !file_exists($realPath)) exit("{$path} error \n");
while (true) {
$client = stream_socket_accept($this->serv);
if ($client) {
$buf = fread($client, 2048);
$classRet = preg_match('/Rpc-Class:\s(.*);\r\n/i', $buf, $class);
$methodRet = preg_match('/Rpc-Method:\s(.*);\r\n/i', $buf, $method);
$paramsRet = preg_match('/Rpc-Params:\s(.*);\r\n/i', $buf, $params);
if ($classRet && $methodRet) {
$class = ucfirst($class[1]);
$file = $realPath . '/' . $class . '.php';
if (file_exists($file)) {
require_once $file;
$obj = new $class();
$data = $paramsRet ? $obj->{$method[1]}(json_decode($params[1], true)) : $obj->{$method[1]}();
fwrite($client, $data);
}
} else {
fwrite($client, 'class or method error');
}
fclose($client);
}
}
}
public function __destruct() { fclose($this->serv); }
}
new RpcServer('127.0.0.1', 8888, './service');The client side (RpcClient.php) parses a URL to obtain host and port, builds the same protocol string, sends it to the server, reads the response, and returns it as the result of a dynamic method call.
<?php
class RpcClient {
protected $urlInfo = array();
public function __construct($url) {
$this->urlInfo = parse_url($url);
if (!$this->urlInfo) exit("{$url} error \n");
}
public function __call($method, $params) {
$client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
if (!$client) exit("{$errno} : {$errstr} \n");
$class = basename($this->urlInfo['path']);
$proto = "Rpc-Class: {$class};" . PHP_EOL;
$proto .= "Rpc-Method: {$method};" . PHP_EOL;
$proto .= "Rpc-Params: " . json_encode($params) . ";" . PHP_EOL;
fwrite($client, $proto);
$data = fread($client, 2048);
fclose($client);
return $data;
}
}
$cli = new RpcClient('http://127.0.0.1:8888/test');
echo $cli->hehe();
echo $cli->hehe2(array('name' => 'test', 'age' => 27));Running the server and client scripts with php RpcServer.php and php RpcClient.php produces the expected output, demonstrating successful remote method invocation.
A simple service class (Test.php) provides two methods, hehe returning a string and hehe2 returning JSON‑encoded parameters, illustrating how the RPC framework can be extended.
<?php
class Test {
public function hehe() { return 'hehe'; }
public function hehe2($params) { return json_encode($params); }
}The directory layout includes the server script, client script, service classes, and the custom protocol can be modified as long as both sides agree on the format.
Overall, the tutorial offers a practical, language‑agnostic example of building an RPC mechanism using PHP sockets, suitable for learning backend network programming.
php中文网 Courses
php中文网's platform for the latest courses and technical articles, helping PHP learners advance quickly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.