The full name of RPC is remote procedure call, which translates as “remote procedure call”. It is mainly used in remote communication and mutual call between different systems.
For example, there are two systems, one is written in PHP and the other is written in Java. If PHP wants to call a method of a class in Java, RPC is needed.
How to adjust it? It’s impossible to call directly. PHP can only request the service of Java through some custom protocol. Java parses the protocol, instantiates the class locally and calls the method, and then returns the result to PHP.
Here we use the socket extension of PHP to create a server and a client to demonstrate the calling process.
RpcServer.php The code is as follows:
serv = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr);
if (!$this->serv) {
exit("{$errno} : {$errstr} \n");
}
//Determine whether our RPC service directory exists
$realPath = realpath(__DIR__ . $path);
if ($realPath === false || !file_exists($realPath)) {
exit("{$path} error \n");
}
while (true) {
$client = stream_socket_accept($this->serv);
if ($client) {
//Here, for simplicity, we read it all at once
$buf = fread($client, 2048);
//Parsing the protocol sent by the client
$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';
//Judge whether the file exists, if so, import the file
if(file_exists($file)) {
require_once $file;
//Instantiate the class and call the method specified by the client
$obj = new $class();
//If there are parameters, the specified parameters are passed in
if(!$paramsRet) {
$data = $obj->$method[1]();
} else {
$data = $obj->$method[1](json_decode($params[1], true));
}
//Return the running result to the client
fwrite($client, $data);
}
} else {
fwrite($client, 'class or method error');
}
//Close client
fclose($client);
}
}
}
public function __destruct() {
fclose($this->serv);
}
}
new RpcServer('127.0.0.1', 8888, './service');
RpcClient.php The code is as follows:
urlInfo = parse_url($url);
if(!$this->urlInfo) {
exit("{$url} error \n");
}
}
public function __call($method, $params) {
//Create a client
$client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
if (!$client) {
exit("{$errno} : {$errstr} \n");
}
//Pass the class name of the call
$class = basename($this->urlInfo['path']);
$proto = "Rpc-Class: {$class};" . PHP_EOL;
//Pass the method name of the call
$proto .= "Rpc-Method: {$method};" . PHP_EOL;
//Pass the parameters of the method
$params = json_encode($params);
$proto .= "Rpc-Params: {$params};" . PHP_EOL;
//Send our custom protocol data to the server
fwrite($client, $proto);
//Read the data from the server
$data = fread($client, 2048);
//Close client
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));
Then run the above two scripts separately (note that PHP needs to add environment variables)
> php RpcServer.php
> php RpcClient.php
The results are as follows
Test.php The code is as follows:
The directory structure is as follows:
The above custom protocol can be modified at will, as long as the client and server can be unified and parsed.
By requesting the server, the client passes the class, method and parameter to be called to the server, and the server returns the result by instantiating the calling method.
For those interested in PHP back-end technology and PHP architecture technology, my official group is 1023755567Click here Learn together and discuss with each other.
There is already management in the group to sort out the knowledge system (source code, learning video and other materials). You are welcome to get it for free.
PHP advanced learning mind map, interview; free access to documents and video resources