douyu1656 2016-04-13 21:45
浏览 210
已采纳

使用curl调用golang调用jsonrpc

I've "hello world" rpc service written on golang. It works fine and go jsonrpc client is working. But I need to send request with curl and this example doesn't work:

curl \
-X POST \
-H "Content-Type: application/json" \
-d '{"id": 1, "method": "Test.Say", "params": [{"greet": "world"}]}' \
http://localhost:1999/_goRPC_

Go accept connection but produce absolutely no result:

curl: (52) Empty reply from server 

Here my go code:

package main

import (
  "log"
  "os"
  "time"
  "net"
  "net/rpc"
  "net/rpc/jsonrpc"
)

// RPC Api structure
type Test struct {}

// Greet method arguments
type GreetArgs struct {
  Name string
}

// Grret message accept object with single param Name
func (test *Test) Greet(args *GreetArgs, result *string) (error) {
  *result = "Hello " + args.Name
  return nil
}

// Start server with Test instance as a service
func startServer(ch chan<- bool, port string) {
  test := new(Test)

  server := rpc.NewServer()
  server.Register(test)

  listener, err := net.Listen("tcp", ":" + port)

  if err != nil {
      log.Fatal("listen error:", err)
  }

  defer listener.Close()

  for {
      conn, err := listener.Accept()

      if err != nil {
          log.Fatal(err)
      }

      go server.ServeCodec(jsonrpc.NewServerCodec(conn))
      ch <- true
  }
}

// Start client and call Test.Greet method
func startClient(port string) {
  conn, err := net.Dial("tcp", ":" + port)

  if err != nil {
      panic(err)
  }
  defer conn.Close()

  c := jsonrpc.NewClient(conn)

  var reply string
  var args = GreetArgs{"world"}
  err = c.Call("Test.Greet", args, &reply)
  if err != nil {
      log.Fatal("arith error:", err)
  }
  log.Println("Result: ", reply)
}

func main() {
  if len(os.Args) < 2 {
    log.Fatal("port not specified")
  }

  port := os.Args[1]
  ch := make(chan bool)

  go startServer(ch, port)
  time.Sleep(500 * time.Millisecond)
  go startClient(port)

  // Produce log message each time connection closes
  for {
    <-ch
    log.Println("Closed")
  }
}
  • 写回答

2条回答 默认 最新

  • dongwei3866 2016-04-14 02:07
    关注

    The jsonrpc package doesn't support json-rpc over HTTP currently. So, you can't call jsonrpc with curl. If you really want to do that, you can make a HTTP handler that adapts the HTTP request/response to a ServerCodec. For example:

    package main
    
    import (
        "io"
        "log"
        "net"
        "net/http"
        "net/rpc"
        "net/rpc/jsonrpc"
        "os"
    )
    
    type HttpConn struct {
        in  io.Reader
        out io.Writer
    }
    
    func (c *HttpConn) Read(p []byte) (n int, err error)  { return c.in.Read(p) }
    func (c *HttpConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }
    func (c *HttpConn) Close() error                      { return nil }
    
    // RPC Api structure
    type Test struct{}
    
    // Greet method arguments
    type GreetArgs struct {
        Name string
    }
    
    // Grret message accept object with single param Name
    func (test *Test) Greet(args *GreetArgs, result *string) error {
        *result = "Hello " + args.Name
        return nil
    }
    
    // Start server with Test instance as a service
    func startServer(port string) {
        test := new(Test)
    
        server := rpc.NewServer()
        server.Register(test)
    
        listener, err := net.Listen("tcp", ":"+port)
    
        if err != nil {
            log.Fatal("listen error:", err)
        }
    
        defer listener.Close()
        http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    
            if r.URL.Path == "/test" {
                serverCodec := jsonrpc.NewServerCodec(&HttpConn{in: r.Body, out: w})
                w.Header().Set("Content-type", "application/json")
                w.WriteHeader(200)
                err := server.ServeRequest(serverCodec)
                if err != nil {
                    log.Printf("Error while serving JSON request: %v", err)
                    http.Error(w, "Error while serving JSON request, details have been logged.", 500)
                    return
                }
            }
    
        }))
    }
    
    func main() {
        if len(os.Args) < 2 {
            log.Fatal("port not specified")
        }
    
        port := os.Args[1]
    
        startServer(port)
    }
    

    Now you can call it with curl -X POST -H "Content-Type: application/json" -d '{"id": 1, "method": "Test.Greet", "params": [{"name":"world"}]}' http://localhost:port/test

    Part of the code is from this post

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 矩阵加法的规则是两个矩阵中对应位置的数的绝对值进行加和
  • ¥15 活动选择题。最多可以参加几个项目?
  • ¥15 飞机曲面部件如机翼,壁板等具体的孔位模型
  • ¥15 vs2019中数据导出问题
  • ¥20 云服务Linux系统TCP-MSS值修改?
  • ¥20 关于#单片机#的问题:项目:使用模拟iic与ov2640通讯环境:F407问题:读取的ID号总是0xff,自己调了调发现在读从机数据时,SDA线上并未有信号变化(语言-c语言)
  • ¥20 怎么在stm32门禁成品上增加查询记录功能
  • ¥15 Source insight编写代码后使用CCS5.2版本import之后,代码跳到注释行里面
  • ¥50 NT4.0系统 STOP:0X0000007B
  • ¥15 想问一下stata17中这段代码哪里有问题呀