Golang

Only methods that satisfy these criteria will be made available for remote access; other methods will be ignored:

  • the method’s type is exported.
  • the method is exported.
  • the method has two arguments, both exported (or builtin) types.
  • the method’s second argument is a pointer.
  • the method has return type error.
// func (t *T) MethodName(argType T1, replyType *T2) error
 
package main
 
import (
	"fmt"
	"log"
	"net"
	"net/rpc"
	"sync"
)
 
//
// Common RPC request/reply definitions
//
 
type PutArgs struct {
	Key   string
	Value string
}
 
type PutReply struct {
}
 
type GetArgs struct {
	Key string
}
 
type GetReply struct {
	Value string
}
 
//
// Client
//
 
func connect() *rpc.Client {
	client, err := rpc.Dial("tcp", ":1234")
	if err != nil {
		log.Fatal("dialing:", err)
	}
	return client
}
 
func get(key string) string {
	client := connect()
	args := GetArgs{"subject"}
	reply := GetReply{}
	err := client.Call("KV.Get", &args, &reply)
	if err != nil {
		log.Fatal("error:", err)
	}
	client.Close()
	return reply.Value
}
 
func put(key string, val string) {
	client := connect()
	args := PutArgs{"subject", "6.824"}
	reply := PutReply{}
	err := client.Call("KV.Put", &args, &reply)
	if err != nil {
		log.Fatal("error:", err)
	}
	client.Close()
}
 
//
// Server
//
 
type KV struct {
	mu   sync.Mutex
	data map[string]string
}
 
func server() {
	kv := &KV{data: map[string]string{}}
	rpcs := rpc.NewServer()
	rpcs.Register(kv)
	l, e := net.Listen("tcp", ":1234")
	if e != nil {
		log.Fatal("listen error:", e)
	}
	go func() {
		for {
			conn, err := l.Accept()
			if err == nil {
				go rpcs.ServeConn(conn)
			} else {
				break
			}
		}
		l.Close()
	}()
}
 
func (kv *KV) Get(args *GetArgs, reply *GetReply) error {
	kv.mu.Lock()
	defer kv.mu.Unlock()
 
	reply.Value = kv.data[args.Key]
 
	return nil
}
 
func (kv *KV) Put(args *PutArgs, reply *PutReply) error {
	kv.mu.Lock()
	defer kv.mu.Unlock()
 
	kv.data[args.Key] = args.Value
 
	return nil
}
 
//
// main
//
 
func main() {
	server()
 
	put("subject", "6.5840")
	fmt.Printf("Put(subject, 6.5840) done\n")
	fmt.Printf("get(subject) -> %s\n", get("subject"))
}