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