2017-07-03 9 views
0

JSON-RPCの仕組みを学び、Go言語(golang)でテストしています。 Goプログラムは正常に動作します。それは何をすべきかをします。しかし、私がtelnetを介して生のリクエストをしようとすると、エラーが発生します。JSON-RPCは「オブジェクトを非整列化できません」

作業と超シンプルなJSON-RPCサーバーがここで説明されています

// rpc_json_server.go 

    package main 

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

    //------------------------------------------------------------------------------ 
    // Types 
    //------------------------------------------------------------------------------ 

    type Arithmetic int // Used as RPC Service called 'Arithmetic' 

    type Arguments struct { 
     A int 
     B int 
    } 

    type Result int 

    //------------------------------------------------------------------------------ 
    // Methods 
    //------------------------------------------------------------------------------ 

    func (t *Arithmetic) Multiply(args *Arguments, res *Result) error { 

     *res = Result(args.A * args.B) 

     return nil 
    } 

    //------------------------------------------------------------------------------ 

    func main() { 

     var srv *rpc.Server 
     var err error 
     var arith *Arithmetic 
     var listener net.Listener 
     var codec rpc.ServerCodec 
     var srv_conntype, srv_host, srv_port, srv_addr, srv_path string 
     var srv_debugPath string 
     var connection net.Conn 

     srv_conntype = "tcp" 
     srv_host = "0.0.0.0" 
     srv_port = "3000" 
     srv_addr = srv_host + ":" + srv_port 
     srv_path = "/" 
     srv_debugPath = "/debug" 

     // Create Server, register Service 
     srv = rpc.NewServer() 
     arith = new(Arithmetic) 
     err = srv.Register(arith) 
     if err != nil { 
      log.Fatalf("Error. Service Format is not correct. %s\r\n", err) //dbg 
     } 

     // Handle, listen 
     srv.HandleHTTP(srv_path, srv_debugPath) 
     listener, err = net.Listen(srv_conntype, srv_addr) 
     if err != nil { 
      log.Fatalf("Error. Can not listen on %s. %s\r\n", srv_addr, err) //dbg 
     } 
     log.Printf("Started RPC Handler at %s.\r\n", srv_addr) //dbg 

     // Serve 
     for { 

      connection, err = listener.Accept() 
      if err != nil { 
       log.Fatal(err) 
      } 

      codec = jsonrpc.NewServerCodec(connection) 

      go srv.ServeCodec(codec) 
     } 

     err = http.Serve(listener, nil) 
     if err != nil { 
      log.Fatalf("Serve Error. %s\r\n", err) //dbg 
     } 
    } 

    //------------------------------------------------------------------------------ 

作業と超シンプルなJSON-RPCクライアントのコードは以下の通りです:

// rpc_json_client.go 

    package main 

    import (
     "fmt" 
     "log" 
     "net" 
     "net/rpc" 
     "net/rpc/jsonrpc" 
    ) 

    //------------------------------------------------------------------------------ 
    // Types 
    //------------------------------------------------------------------------------ 

    type Arithmetic int // Used as RPC Service called 'Arithmetic' 

    type Arguments struct { 
     A int 
     B int 
    } 

    type Result int 

    //------------------------------------------------------------------------------ 
    // Methods 
    //------------------------------------------------------------------------------ 

    func main() { 

     var err error 
     var srv_conntype, srv_host, srv_port, srv_addr string 
     //var srv_path string 
     var client *rpc.Client 
     var args Arguments 
     var result Result 
     var serviceName, methodName, funcName string 
     var connection net.Conn 

     srv_conntype = "tcp" 
     srv_host = "0.0.0.0" 
     srv_port = "3000" 
     srv_addr = srv_host + ":" + srv_port 
     //srv_path = "/" 

     // Connect to RPC Server 
     connection, err = net.Dial(srv_conntype, srv_addr) 
     if err != nil { 
      log.Fatalf("Error. Can not connect to %s. %s\r\n", srv_addr, err) //dbg 
     } 
     defer connection.Close() 

     // Client 
     client = jsonrpc.NewClient(connection) 

     // Prepare Call 
     serviceName = "Arithmetic" 
     methodName = "Multiply" 
     funcName = serviceName + "." + methodName 
     args.A = 7 
     args.B = 8 

     // Call remote Procedure 
     err = client.Call(funcName, args, &result) 
     if err != nil { 
      log.Fatalf("Error. %s\r\n", err) //dbg 
     } 

     // Show Results 
     fmt.Printf("[%d; %d] -> [%d].\r\n", args.A, args.B, result) //dbg 
    } 

もう一度。このゴランプログラムはうまく動作します。

しかし私は理解できません。

telnet localhost 3000 
    Trying 127.0.0.1... 
    Connected to localhost. 
    Escape character is '^]'. 
    { 
    "jsonrpc":"2.0", 
    "method":"Arithmetic.Multiply", 
    "params": { "A": 5, "B": 6 }, 
    "id":1 
    } 
    {"id":1,"result":null,"error":"json: cannot unmarshal object into Go value of type [1]interface {}"} 

私には、このようなエラーのいくつかのアドバイスや理由を教えてください。生のリクエストで何が間違っていますか?

ありがとうございます!

+0

現在の実装/ JSONRPC 1つの引数を取りますstructの引数のために。 https://github.com/golang/go/blob/5fea2ccc77eb50a9704fa04b7c61755fe34e1d95/src/net/rpc/jsonrpc/server.go#L91-L97名前付き引数を渡したい場合は、structのsliceとして渡してください。 – mattn

答えて

1

コードは正常です。

しかし、リクエストでは、paramsは実際のパラメータを含む配列であると予想されます。

次のペイロードで試してみて、それが動作するはずです:

{ 
    "jsonrpc":"2.0", 
    "method":"Arithmetic.Multiply", 
    "params": [ { "A": 5, "B": 6 } ], 
    "id":1 
} 

(実際のparamを囲む "[" と "]" に注意してください)ネット/ RPCの

+0

それは動作します!あなたに多くのおかげで:) – Chelovek

関連する問題