首先,说一下目录结构:

一、HttpRPC

1、建立服务文件

/*Go RPC的函数只有符合下面的条件才能被远程访问,不然会被忽略,详细的要求如下:
函数必须是导出的(首字母大写)
必须有两个导出类型的参数,
第一个参数是接收的参数,第二个参数是返回给客户端的参数,第二个参数必须是指针类型的
函数还要有一个返回值error
举个例子,正确的RPC函数格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error
*/
package common

import (
	"errors"
)

type Args struct {
	A, B float32
}
type Result struct {
	Value float32
}
type MathService struct {
}

func (s *MathService) Add(args *Args, result *Result) error {
	result.Value = args.A + args.B
	return nil
}

func (s *MathService) Divide(args *Args, result *Result) error {
	if args.B == 0 {
		return errors.New("除数不能为零!")
	}
	result.Value = args.A / args.B
	return nil
}

  

2、服务端代码:  

package main

import (
	"fmt"
	"net/http"
	"net/rpc"

	"../common"
)

func main() {
	var ms = new(common.MathService)
	rpc.Register(ms)
	rpc.HandleHTTP() //将Rpc绑定到HTTP协议上。
	fmt.Println("启动服务...")
	err := http.ListenAndServe(":1234", nil)
	if err != nil {
		fmt.Println(err.Error())
	}
	fmt.Println("服务已停止!")
}

3、客户端调用代码:

package main

import (
	"fmt"
	"net/rpc"

	"../common"
)

func main() {
	var args = common.Args{17, 8}
	var result = common.Result{}

	var client, err = rpc.DialHTTP("tcp", "127.0.0.1:1234")
	if err != nil {
		fmt.Println("连接RPC服务失败:", err)
	}
	err = client.Call("MathService.Divide", args, &result)
	if err != nil {
		fmt.Println("调用失败:", err)
	}
	fmt.Println("调用结果:", result.Value)
}

4、测试:

 

 

二、HttpRPC

1、建立服务文件

/*Go RPC的函数只有符合下面的条件才能被远程访问,不然会被忽略,详细的要求如下:
函数必须是导出的(首字母大写)
必须有两个导出类型的参数,
第一个参数是接收的参数,第二个参数是返回给客户端的参数,第二个参数必须是指针类型的
函数还要有一个返回值error
举个例子,正确的RPC函数格式如下:
func (t *T) MethodName(argType T1, replyType *T2) error
*/
package common

import (
	"errors"
)

type Args struct {
	A, B float32
}
type Result struct {
	Value float32
}
type MathService struct {
}

func (s *MathService) Add(args *Args, result *Result) error {
	result.Value = args.A + args.B
	return nil
}

func (s *MathService) Divide(args *Args, result *Result) error {
	if args.B == 0 {
		return errors.New("除数不能为零!")
	}
	result.Value = args.A / args.B
	return nil
}

2、服务端文件

package main

import (
	"fmt"
	"net"
	"net/rpc"

	"../common"
)

func main() {
	var ms = new(common.MathService) //实例化服务对像
	rpc.Register(ms)                 //注册这个服务
	fmt.Println("启动服务...")
	var address, _ = net.ResolveTCPAddr("tcp", "127.0.0.1:1234") //定义TCP的服务承载地址
	listener, err := net.ListenTCP("tcp", address)               //监听TCP连接
	if err != nil {
		fmt.Println("启动失败!", err)
	}
	for {
		conn, err := listener.Accept() //如果接受到连接
		if err != nil {
			continue
		}
		fmt.Println("接收到一个调用请求...")
		rpc.ServeConn(conn) //让此rpc绑定到该Tcp连接上。
	}
	//fmt.Println("服务已停止!")
}

3、客户端代码:

// main.go
package main

import (
	"fmt"
	"net/rpc"

	"../common"
)

func main() {
	var client, err = rpc.Dial("tcp", "127.0.0.1:1234")
	if err != nil {
		fmt.Println("连接不到服务器:", err)
	}
	var args = common.Args{40, 3}
	var result = common.Result{}
	fmt.Println("开始调用!")
	err = client.Call("MathService.Add", args, &result)
	if err != nil {
		fmt.Println("调用失败!", err)
	}
	fmt.Println("调用成功!结果:", result.Value)
}

4、效果: