2016-04-13 13 views
3

Ben "Merhaba dünya" rpc servisi golang üzerinde yazdım. İyi çalışıyor ve jsonrpc istemci çalışıyor. Ama Kıvrık isteği göndermek gerekiyor ve bu örnek çalışmaz:Arama golang call jsonrpc ile birlikte

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

Git bağlantıyı kabul ama kesinlikle hiçbir sonuç üretmek:

İşte
curl: (52) Empty reply from server 

zaman git kodu:

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") 
    } 
} 

cevap

6

jsonrpc paketi şu anda HTTP üzerinden json-rpc'yi desteklemiyor. Yani, jsonrpc'i curl ile arayamazsın. Bunu gerçekten yapmak istiyorsanız, HTTP isteğini/yanıtını ServerCodec'a göre ayarlayan bir HTTP işleyicisi oluşturabilirsiniz. Örneğin:

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) 
} 

Şimdi kodun curl -X POST -H "Content-Type: application/json" -d '{"id": 1, "method": "Test.Greet", "params": [{"name":"world"}]}' http://localhost:port/test

Bölüm ile diyebilirsin this post

+0

Güzel görünmüyor. Ama işe yarıyor! Teşekkürler) Belki bu kod ayrı bir paket olmalı? –

+0

Evet, sadece basit bir örnek. Aslında, zaten böyle paketler var, [burada] (http://github.com/gorilla/rpc/json) bir. – jfly

+0

Tek başına bir paket mi? –

3

@jfly şık çözümü vardır değil.

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} 

: Hala jsonrpc cient (muhtemelen en kolay seçenek) gitmek veya kullanım @ jfly cevabı yanında bir şeyle test etmek istiyorsa

Başka bir seçenek, ham veri göndermek için telnet kullanabileceği başka Yukarıda yazdığım yük ve sunucunuzun yanıtları dahil çıktı. Göndermek için doğru yükü bulurken tcpdump benim arkadaşımdı.

+0

Eklediğiniz için teşekkürler. –