Go语言中Tcp实现Rpc

 更新时间:2026年07月07日 09:08:00   作者:H_拾忆  
本文主要介绍了Go语言中Tcp实现Rpc,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

1.Tcp实现Rpc:

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

1.1服务端:

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客户端:

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服务端:

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源码:

func ServeConn(conn io.ReadWriteCloser) {
	rpc.ServeCodec(NewServerCodec(conn))
}

2.3NewServerCodec源码:

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

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客户端:

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

到此这篇关于Go语言中Tcp实现Rpc的文章就介绍到这了,更多相关Go Tcp实现Rpc内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • go module构建项目的实现

    go module构建项目的实现

    本文主要介绍了go module构建项目的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • golang利用unsafe操作未导出变量-Pointer使用详解

    golang利用unsafe操作未导出变量-Pointer使用详解

    这篇文章主要给大家介绍了关于golang利用unsafe操作未导出变量-Pointer使用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧
    2018-08-08
  • GO使用阿里云,解决go get下载项目慢或无法下载的情况

    GO使用阿里云,解决go get下载项目慢或无法下载的情况

    这篇文章主要介绍了GO使用阿里云,解决go get下载项目慢或无法下载的情况,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Go无缓冲通道(同步通道)的实现

    Go无缓冲通道(同步通道)的实现

    本文主要介绍了Go无缓冲通道(同步通道)的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • Go语言中的日期与时间用法详细介绍

    Go语言中的日期与时间用法详细介绍

    Go语言提供了丰富的日期与时间处理函数,涵盖了从获取当前时间到格式化、时区转换、定时器和计时器的功能,这篇文章主要给大家介绍了关于Go语言中日期与时间用法的相关资料,需要的朋友可以参考下
    2024-06-06
  • Go Generate 代替 Makefile使用方法详解

    Go Generate 代替 Makefile使用方法详解

    这篇文章主要为大家介绍了Go Generate 代替 Makefile使用方法详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Go语言sync.Cond基本使用及原理示例详解

    Go语言sync.Cond基本使用及原理示例详解

    这篇文章主要为大家介绍了Go语言sync.Cond基本使用及原理示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • Go语言中的数据竞争模式详解

    Go语言中的数据竞争模式详解

    这篇文章主要介绍了Go语言中的数据竞争模式详解,主要基于在Uber的Go monorepo中发现的各种数据竞争模式,分析了其背后的原因与分类,需要的朋友可以参考一下
    2022-07-07
  • Go标准库Flag库和Log库的使用

    Go标准库Flag库和Log库的使用

    本文主要介绍了Go标准库Flag库和Log库的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • Go语言中init函数特点、用途和注意事项详解

    Go语言中init函数特点、用途和注意事项详解

    go语言中有一个非常神奇的函数init,它可以在所有程序执行开始前被执行,并且每个package下面可以存在多个init函数,这篇文章主要给大家介绍了关于Go语言中init函数特点、用途和注意事项的相关资料,需要的朋友可以参考下
    2023-07-07

最新评论