Go & PHP json-rpc 通信

Posted

技术标签:

【中文标题】Go & PHP json-rpc 通信【英文标题】:Go & PHP json-rpc communication 【发布时间】:2018-05-02 19:36:11 【问题描述】:

我尝试在 php 和 go 之间通信 JSON-RPC。

此示例中的服务器 GO https://golang.org/pkg/net/rpc/

package main

import (
    "errors"
    "net/rpc"
    "net"
    "log"
    "net/http"
)

type Args struct 
    A, B int


type Quotient struct 
    Quo, Rem int


type Arith int

func (t *Arith) Multiply(args *Args, reply *int) error 
    *reply = args.A * args.B
    return nil


func (t *Arith) Divide(args *Args, quo *Quotient) error 
    if args.B == 0 
        return errors.New("divide by zero")
    
    quo.Quo = args.A / args.B
    quo.Rem = args.A % args.B
    return nil



func main() 
    arith := new(Arith)
    rpc.Register(arith)
    rpc.HandleHTTP()
    l, e := net.Listen("tcp", ":4444")
    if e != nil 
        log.Fatal("listen error:", e)
    
//  go http.Serve(l, nil)

    err:= http.Serve(l, nil)
    if err != nil 
        log.Fatalf("Error serving: %s", err)
    


和来自此存储库的示例中的 php 客户端 https://github.com/ptcx/jsonrpc-client:

require 'vendor/autoload.php';

$client = new JRClient\Client('tcp', '127.0.0.1:4444');
sleep(5);
$result = $client->call('Arith.Multiply', ['A' => 3, "B" => 4], 1000);
if ($result['error']) 
    echo $result['errorMsg'] . "\n";
 else 
    var_dump($result['data']);

Bur final 我有错误:HTTP/1.1 400 Bad Request 我也试过在 php connect 之后写 sleep(5) 但没有结果?我还尝试从 false 上的 true 更改为函数 stream_set_blocking($this->sockfp, false) https://github.com/ptcx/jsonrpc-client/blob/master/src/Connection/TcpConnection.php#L69 - 没有结果。 我编写了 GO 客户端 - 它可以正常工作。

请帮助我使用我的 php 客户端

【问题讨论】:

一个 400 响应意味着有一个错误的请求和一个 响应,所以它不是连接或阻塞。您是否查看过每个客户的实际请求以了解它们有何不同? @JimB 好主意。但是我该怎么做会有所不同,哪种方式? 我不确定我是否理解。这些是相当简单的请求,您应该能够通过查看它们直观地发现任何差异。 【参考方案1】:

当您调用rpc.HandleHTTP() 时,您正在使用 gobs 编码和解码。阅读更多关于 gob 的信息:https://blog.golang.org/gobs-of-data 和 https://golang.org/pkg/encoding/gob/。

在https://golang.org/src/net/rpc/server.go 文件中,您可以阅读:

要在 Go 中使用 jsonrpc,您必须使用包 net/rpc/jsonrpc 中的编解码器,而不是 net/rpc。

jsonrpc 包实现了一个 JSON-RPC 1.0 ClientCodec 和 ServerCodec 对于 rpc 包。对于 JSON-RPC 2.0 支持 [...]

(参考来源:https://golang.org/pkg/net/rpc/jsonrpc/)

所以上面跟着main.go中的代码:

func main() 
    //arith instance
    arith := new(Arith)

    //make listen in 127.0.0.1:4444
    l, e := net.Listen("tcp", ":4444")
    if e != nil 
        log.Fatal("listen error:", e)
    
    defer l.Close()

    //instance rpc server
    rpcserver := rpc.NewServer()
    rpcserver.Register(arith)
    //updated for multiples requests
    for 
        //block until acceptation of client
        c, e := l.Accept()
        if e != nil 
          log.Fatal("accept error:", e)
        
        //instance codec
        jsoncodec := jsonrpc.NewServerCodec(c)
        rpcserver.ServeCodec(jsoncodec)
    

在 exec php client.php 上,结果是:

更新:在 php 文件中:

<?php
//imports
require 'vendor/autoload.php';
//instance client
$client = new JRClient\Client('tcp', '127.0.0.1:4444');

//sleep(5); <<-- remove

//call method 'Arith.Multiply'
$result = $client->call('Arith.Multiply', ['A' => 3, "B" => 4], 1000);
if ($result['error']) 
    echo $result['errorMsg'] . "\n";
 else 
    var_dump($result['data']);


?>

希望这会有所帮助!

【讨论】:

感谢您的帮助,但是如果我第一次在 go 服务器上使用新代码运行 php 客户端,我会收到错误 "id":1,"result":null,"error":"rpc : 找不到服务 Arith.Multiply" github.com/golang/go/blob/master/src/net/rpc/server.go#L614 和第二次:"超时错误" go version go1.9.4 linux/amd64 and php 5.6

以上是关于Go & PHP json-rpc 通信的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PHP 中构造 JSON-RPC 结构中的 CURL?

用于 PHP 的 JSON-RPC 2 客户端能够调用嵌套类中的方法

企信通群发平台;java;.net开发

Go中基于HTTP的JSONRPC [重复]

JSON-RPC PHP 类未找到错误

Swagger 和 json-rpc