Go语言学习笔记(十二)Tcp实现Rpc

1.Tcp实现Rpc:

既然可以直接利用Tcp传递消息,相对于Http来说便不在需要相关处理..同时利用Http实现Rpc时,服务端可以自动接管网络连接.然后负责对象连接管理.Tcp只能自行处理.

1.1服务端:

go 复制代码
package main

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

func main() {
	rpc.Register(new(UserHandler))
	listen, err := net.Listen("tcp", "127.0.0.1:8090")

	if err != nil {
		fmt.Println("监听tcp端口出错")
		return
	}

	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("建立tcp连接失败")
			continue
		}

		go func(conn net.Conn) {
			rpc.ServeConn(conn)
		}(conn)
	}
}

type UserHandler struct {
}

type Userdetail struct {
	Id       int
	Username string
	Nickname string
}

// 获取用户信息的方法绑定到结构体
func (handler *UserHandler) GetUserInfo(name string, user *Userdetail) (err error) {
	fmt.Println("try to get user info by %s", name)

	//校验入参.
	if len(name) == 0 {
		return errors.New("the user name is empty")
	}

	user.Id = 001
	user.Username = "itbo"
	user.Nickname = "尊敬的itbo"

	return nil
}

1.2客户端:

go 复制代码
package main

import (
	"fmt"
	"net/rpc"
)

func main() {
	//利用Tcp连接远程服务端.
	client, err := rpc.Dial("tcp", "127.0.0.1:8090")
	if err != nil {
		fmt.Println("与服务端建立连接出错")
		return
	}

	defer client.Close()

	user := new(Userdetail)
	client.Call("UserHandler.GetUserInfo", "golang", user)

	if err != nil {
		fmt.Println("获取用户信息出错", err)
		return
	}
	//打印获取的信息
	fmt.Printf("用户id:%+v\n", user.Id)
	fmt.Printf("用户名:%+v\n", user.Username)
	fmt.Printf("用户昵称:%+v\n", user.Nickname)

}

1.3执行结果:

1.4Http和Tcp实现Rpc区别:

Tcp实现的服务端代码失去了rpc.HandleHttp和http.Serve这两个函数的调用.其中rpc.HandleHttp用于注册默认的url和处理函数的映射关系.

打开http.service源码可以看到.

通过这里接收连接然后去处理.因为没有调用这个函数.所以tcp需要自己去处理连接.

2.Json格式实现Rpc通信:

2.1服务端:

go 复制代码
package main

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

func main() {
	rpc.Register(new(UserHandler))
	listen, err := net.Listen("tcp", "127.0.0.1:8090")

	http.Serve(listen, nil)
	if err != nil {
		fmt.Println("监听tcp端口出错")
		return
	}

	for {
		conn, err := listen.Accept()
		if err != nil {
			fmt.Println("建立tcp连接失败")
			continue
		}

		go func(conn net.Conn) {
			//利用jsonRpc处理连接.
			jsonrpc.ServeConn(conn)
		}(conn)
	}
}

type UserHandler struct {
}

type Userdetail struct {
	Id       int
	Username string
	Nickname string
}

// 获取用户信息的方法绑定到结构体
func (handler *UserHandler) GetUserInfo(name string, user *Userdetail) (err error) {
	fmt.Println("try to get user info by %s", name)

	//校验入参.
	if len(name) == 0 {
		return errors.New("the user name is empty")
	}

	user.Id = 001
	user.Username = "itbo"
	user.Nickname = "尊敬的itbo"

	return nil
}

2.2jsonrpc.ServeConn源码:

scss 复制代码
func ServeConn(conn io.ReadWriteCloser) {
	rpc.ServeCodec(NewServerCodec(conn))
}

2.3NewServerCodec源码:

可以看到底层有一个编码器和解码器.

go 复制代码
func NewServerCodec(conn io.ReadWriteCloser) rpc.ServerCodec {
	return &serverCodec{
		dec:     json.NewDecoder(conn),
		enc:     json.NewEncoder(conn),
		c:       conn,
		pending: make(map[uint64]*json.RawMessage),
	}
}

2.4客户端:

go 复制代码
package main

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

func main() {
	//利用Tcp连接远程服务端.
	//client, err := rpc.Dial("tcp", "127.0.0.1:8090")
	client, err := jsonrpc.Dial("tcp", "127.0.0.1:8090")
	if err != nil {
		fmt.Println("与服务端建立连接出错")
		return
	}

	defer client.Close()

	user := new(Userdetail)
	client.Call("UserHandler.GetUserInfo", "golang", user)

	if err != nil {
		fmt.Println("获取用户信息出错", err)
		return
	}
	//打印获取的信息
	fmt.Printf("用户id:%+v\n", user.Id)
	fmt.Printf("用户名:%+v\n", user.Username)
	fmt.Printf("用户昵称:%+v\n", user.Nickname)
}
相关推荐
JaguarJack17 分钟前
PHP Trait 为何可能成为语言的关键特性
后端·php·服务端
n8n29 分钟前
多 Agent 协作实战:Supervisor 模式构建专家团队,突破单一 Agent 能力边界
后端
BingoGo29 分钟前
PHP Trait 为何可能成为语言的关键特性
后端·php
名字还没想好☜34 分钟前
Python 的 __call__ 实战:让实例像函数一样被调用,做带状态计数器、缓存器与可配置策略
开发语言·后端·python·缓存·编程语言
杨利杰YJlio41 分钟前
ITSK PE 26U5 测试版解读:组件完善、VMD 修复与服务器支持边界
前端·javascript·后端
PragmaticWorks41 分钟前
充血模型该充到什么地步?
后端·领域驱动设计
雨辰AI1 小时前
信创多租户项目 9 大踩坑|数据隔离失效、权限越权终极解决(金仓 / 达梦 / 高斯全库适配)
java·大数据·数据库·后端
广州山泉婚姻1 小时前
微服务时代,前后端分离架构该怎样高效协同?
前端·后端
孙启超1 小时前
【AI开发之Rust】第 5 课:引用与生命周期 —— 借用能活多久?
人工智能·后端·rust·llm·ai应用开发
EatFan1 小时前
多租户系统到底怎么设计?从 tenant_id 到 JWT 租户隔离的真实实践
前端·后端·全栈·多租户