使用 curl 调用 golang jsonrpc

我有用 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 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")

  }

}


HUWWW
浏览 332回答 2
2回答

慕森卡

jsonrpc 包目前不支持通过 HTTP 的 json-rpc。所以,你不能用 curl 调用 jsonrpc。如果你真的想这样做,你可以制作一个 HTTP 处理程序,使 HTTP 请求/响应适应ServerCodec. 例如:package mainimport (&nbsp; &nbsp; "io"&nbsp; &nbsp; "log"&nbsp; &nbsp; "net"&nbsp; &nbsp; "net/http"&nbsp; &nbsp; "net/rpc"&nbsp; &nbsp; "net/rpc/jsonrpc"&nbsp; &nbsp; "os")type HttpConn struct {&nbsp; &nbsp; in&nbsp; io.Reader&nbsp; &nbsp; out io.Writer}func (c *HttpConn) Read(p []byte) (n int, err error)&nbsp; { 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&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { return nil }// RPC Api structuretype Test struct{}// Greet method argumentstype GreetArgs struct {&nbsp; &nbsp; Name string}// Grret message accept object with single param Namefunc (test *Test) Greet(args *GreetArgs, result *string) error {&nbsp; &nbsp; *result = "Hello " + args.Name&nbsp; &nbsp; return nil}// Start server with Test instance as a servicefunc startServer(port string) {&nbsp; &nbsp; test := new(Test)&nbsp; &nbsp; server := rpc.NewServer()&nbsp; &nbsp; server.Register(test)&nbsp; &nbsp; listener, err := net.Listen("tcp", ":"+port)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("listen error:", err)&nbsp; &nbsp; }&nbsp; &nbsp; defer listener.Close()&nbsp; &nbsp; http.Serve(listener, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; &nbsp; &nbsp; if r.URL.Path == "/test" {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; serverCodec := jsonrpc.NewServerCodec(&HttpConn{in: r.Body, out: w})&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.Header().Set("Content-type", "application/json")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; w.WriteHeader(200)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err := server.ServeRequest(serverCodec)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Printf("Error while serving JSON request: %v", err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; http.Error(w, "Error while serving JSON request, details have been logged.", 500)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }))}func main() {&nbsp; &nbsp; if len(os.Args) < 2 {&nbsp; &nbsp; &nbsp; &nbsp; log.Fatal("port not specified")&nbsp; &nbsp; }&nbsp; &nbsp; port := os.Args[1]&nbsp; &nbsp; startServer(port)}现在你可以用 curl -X POST -H "Content-Type: application/json" -d '{"id": 1, "method": "Test.Greet", "params": [{"name":"world"}]}' http://localhost:port/test

ABOUTYOU

另一种选择,如果你仍然想用除了 go jsonrpc cient(可能是最简单的选项)之外的东西进行测试,或者使用@jfly 的答案,你可以使用 telnet 发送原始数据:computer:~ User$ telnet 127.0.0.1 8888Trying 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 是我的朋友。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go