« Back to Index

Ruby client communicating with Go RPC over a TCP socket

View original Gist on GitHub

client.rb

require "socket"
require "json"
require "pry"

socket = TCPSocket.new "localhost", "8080"

# Details of JSON structure can be found here:
# https://golang.org/src/net/rpc/jsonrpc/client.go#L45
# Thanks to Albert Hafvenström (@albhaf) for his help
b = {
  :method => "Compose.Details",
  :params => [{ :Foo => "Foo!", :Bar => "Bar!" }],
  :id     => "0" # id is just echo'ed back to the client
}

binding.pry

socket.write(JSON.dump(b))

p JSON.load(socket.readline)

# => {"id"=>"0", "result"=>"Blah!", "error"=>nil}

server-endpoint.go

package remote

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

// Endpoint exposes our RPC over TCP service
func Endpoint() {
	compose := new(Compose)

	rpc.Register(compose)

	listener, err := net.Listen("tcp", ":8080")
	if err != nil {
		// handle error
	}

	for {
		conn, err := listener.Accept()
		if err != nil {
			// handle error
		}

		go jsonrpc.ServeConn(conn)
	}
}

server-rpc.go

package remote

import "fmt"

// Args is structured around the client's provided parameters
// The fields need to be exported too!
type Args struct {
	Foo string
	Bar string
}

// Compose is our RPC functions return type
type Compose string

// Details is our exposed RPC function
func (c *Compose) Details(args *Args, reply *string) error {
	fmt.Printf("Args received: %+v\n", args)
	*c = "some value"
	*reply = "Blah!"
	return nil
}

// Args received: &{Foo:Foo! Bar:Bar!}