为了账号安全,请及时绑定邮箱和手机立即绑定

使用 curl 调用 golang jsonrpc

使用 curl 调用 golang jsonrpc

Go
HUWWW 2022-01-04 13:36:32
我有用 golang 编写的“hello world”rpc 服务。它工作正常并且 jsonrpc 客户端正在工作。但是我需要用 curl 发送请求,这个例子不起作用:curl \-X POST \-H "Content-Type: application/json" \-d '{"id": 1, "method": "Test.Say", "params": [{"greet": "world"}]}' \http://localhost:1999/_goRPC_去接受连接但绝对没有结果:curl: (52) Empty reply from server 这是我的代码:package mainimport (  "log"  "os"  "time"  "net"  "net/rpc"  "net/rpc/jsonrpc")// RPC Api structuretype Test struct {}// Greet method argumentstype GreetArgs struct {  Name string}// Grret message accept object with single param Namefunc (test *Test) Greet(args *GreetArgs, result *string) (error) {  *result = "Hello " + args.Name  return nil}// Start server with Test instance as a servicefunc 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 methodfunc 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 回答

?
慕森卡

TA贡献1806条经验 获得超8个赞

jsonrpc 包目前不支持通过 HTTP 的 json-rpc。所以,你不能用 curl 调用 jsonrpc。如果你真的想这样做,你可以制作一个 HTTP 处理程序,使 HTTP 请求/响应适应ServerCodec. 例如:


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)

}

现在你可以用 curl -X POST -H "Content-Type: application/json" -d '{"id": 1, "method": "Test.Greet", "params": [{"name":"world"}]}' http://localhost:port/test



查看完整回答
反对 回复 2022-01-04
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

另一种选择,如果你仍然想用除了 go jsonrpc cient(可能是最简单的选项)之外的东西进行测试,或者使用@jfly 的答案,你可以使用 telnet 发送原始数据:


computer:~ User$ telnet 127.0.0.1 8888

Trying 127.0.0.1...

Connected to localhost.

Escape character is '^]'.

{"method":"Test.Greet","params":[{"Name":"world"}],"id":0}

{"id":0,"result":"Hello world","error":null}

{"method":"Test.Greet","params":[{"Name":"world"}],"id":0}

{"id":0,"result":"Hello world","error":null}

{"method":"Test.Greet","params":[{"Name":"world"}],"id":0}

{"id":0,"result":"Hello world","error":null}

以上是输出,包括我输入的有效负载和您的服务器的响应。


当我确定要发送的正确有效负载时,tcpdump 是我的朋友。


查看完整回答
反对 回复 2022-01-04
  • 2 回答
  • 0 关注
  • 331 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号