Example of using go language net package rpc for remote calls

  • 2020-06-12 09:22:27
  • OfStack

The rpc package provides a method to connect to external methods of an object via a network or other I/O connection. Once registered, external methods of the object can be called remotely. An server can register multiple objects of different types, but not multiple objects of the same type.

Only methods that meet these criteria are considered visible by remote calls; Other methods are ignored:

- Methods are externally visible.
- The method takes two arguments, the type of which is externally visible.
- The second argument to the method is 1 pointer.
- Method has a return type error

1. RPC based on http

Server:


package main;

 

import (

  "net/rpc"

  "net/http"

  "log"

)

 

//go right RPC Support, support 3 Two levels: TCP , HTTP , JSONRPC

//go the RPC Only support GO The interaction between the developed server and the client is due to the adoption gob coding 

 

// Note that the fields must be exported 

type Params struct {

  Width, Height int;

}

 

type Rect struct{}

 

// The function must be derived 

// You must have two export type parameters 

// The first 1 The parameters are received parameters 

// The first 2 Parameters are returned to the client and must be of pointer type 

// The function has to have 1 A return value error

func (r *Rect) Area(p Params, ret *int) error {

  *ret = p.Width * p.Height;

  return nil;

}

 

func (r *Rect) Perimeter(p Params, ret *int) error {

  *ret = (p.Width + p.Height) * 2;

  return nil;

}

 

func main() {

  rect := new(Rect);

  // registered 1 a rect service 

  rpc.Register(rect);

  // Bind service processing to http Agreement on 

  rpc.HandleHTTP();

  err := http.ListenAndServe(":8080", nil);

  if err != nil {

    log.Fatal(err);

  }

} 

Client:


package main;

 

import (

  "net/rpc"

  "log"

  "fmt"

)

 

type Params struct {

  Width, Height int;

}

 

func main() {

  // To connect to a remote rpc service 

  rpc, err := rpc.DialHTTP("tcp", "127.0.0.1:8080");

  if err != nil {

    log.Fatal(err);

  }

  ret := 0;

  // Calling a remote method 

  // Note that the first 3 The parameters are of pointer type 

  err2 := rpc.Call("Rect.Area", Params{50, 100}, &ret);

  if err2 != nil {

    log.Fatal(err2);

  }

  fmt.Println(ret);

  err3 := rpc.Call("Rect.Perimeter", Params{50, 100}, &ret);

  if err3 != nil {

    log.Fatal(err3);

  }

  fmt.Println(ret);

} 

2. RPC based on tcp

Server:


package main;

 

import (

  "net"

  "log"

  "net/rpc"

)

 

// Note that the fields must be exported 

type Params struct {

  Width, Height int;

}

 

type Rect struct{}

 

func (r *Rect) Area(p Params, ret *int) error {

  *ret = p.Width * p.Height;

  return nil;

}

 

func (r *Rect) Perimeter(p Params, ret *int) error {

  *ret = (p.Width + p.Height) * 2;

  return nil;

}

 

func chkError(err error) {

  if err != nil {

    log.Fatal(err);

  }

}

 

func main() {

  rect := new(Rect);

  // registered rpc service 

  rpc.Register(rect);

  // To obtain tcpaddr

  tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");

  chkError(err);

  // Listen on port 

  tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);

  chkError(err2);

  // An endless loop processes connection requests 

  for {

    conn, err3 := tcplisten.Accept();

    if err3 != nil {

      continue;

    }

    // use goroutine Individual treatment rpc Connection request 

    go rpc.ServeConn(conn);

  }

} 

Client:


package main;

 

import (

  "net/rpc"

  "fmt"

  "log"

)

 

type Params struct {

  Width, Height int;

}

 

func main() {

  // To connect to a remote rpc service 

  // Used here Dial . http Way to use DialHTTP , the rest of the code 1 sample 

  rpc, err := rpc.Dial("tcp", "127.0.0.1:8080");

  if err != nil {

    log.Fatal(err);

  }

  ret := 0;

  // Calling a remote method 

  // Note that the first 3 The parameters are of pointer type 

  err2 := rpc.Call("Rect.Area", Params{50, 100}, &ret);

  if err2 != nil {

    log.Fatal(err2);

  }

  fmt.Println(ret);

  err3 := rpc.Call("Rect.Perimeter", Params{50, 100}, &ret);

  if err3 != nil {

    log.Fatal(err3);

  }

  fmt.Println(ret);

} 

3. JSON RPC

jsonrpc method USES json instead of gob for data encoding.

Server:


package main;

 

import (

  "net"

  "log"

  "net/rpc"

  "net/rpc/jsonrpc"

)

 

// Note that the fields must be exported 

type Params struct {

  Width, Height int;

}

 

type Rect struct{}

 

func (r *Rect) Area(p Params, ret *int) error {

  *ret = p.Width * p.Height;

  return nil;

}

 

func (r *Rect) Perimeter(p Params, ret *int) error {

  *ret = (p.Width + p.Height) * 2;

  return nil;

}

 

func chkError(err error) {

  if err != nil {

    log.Fatal(err);

  }

}

 

func main() {

  rect := new(Rect);

  // registered rpc service 

  rpc.Register(rect);

  // To obtain tcpaddr

  tcpaddr, err := net.ResolveTCPAddr("tcp4", "127.0.0.1:8080");

  chkError(err);

  // Listen on port 

  tcplisten, err2 := net.ListenTCP("tcp", tcpaddr);

  chkError(err2);

  for {

    conn, err3 := tcplisten.Accept();

    if err3 != nil {

      continue;

    }

    // use goroutine Individual treatment rpc Connection request 

    // Used here jsonrpc For processing 

    go jsonrpc.ServeConn(conn);

  }

} 

Client:


 package main;

 

import (

  "fmt"

  "log"

  "net/rpc/jsonrpc"

)

 

type Params struct {

  Width, Height int;

}

 

func main() {

  // To connect to a remote rpc service 

  // Used here jsonrpc.Dial

  rpc, err := jsonrpc.Dial("tcp", "127.0.0.1:8080");

  if err != nil {

    log.Fatal(err);

  }

  ret := 0;

  // Calling a remote method 

  // Note that the first 3 The parameters are of pointer type 

  err2 := rpc.Call("Rect.Area", Params{50, 100}, &ret);

  if err2 != nil {

    log.Fatal(err2);

  }

  fmt.Println(ret);

  err3 := rpc.Call("Rect.Perimeter", Params{50, 100}, &ret);

  if err3 != nil {

    log.Fatal(err3);

  }

  fmt.Println(ret);

} 


Related articles: