• RPC与Protobuf(五)


    RPC实现上下文信息

    基于上下文可以针对不同的客户端提供定制化的RPC服务,我们可以通过为每个连接提供独立的RPC服务来实现对上下文的特性的支持,下面我们将针对每个RPC服务进行登陆验证,如果通过服务登陆就可以调用RPC,首先是proto目录下的proto文件:

    syntax = "proto3";
    
    package proto;
    
    message String {
        string value = 1;
    }

    当然我们需要使用特殊的命令生成相应的接口文件: protoc --go_out=. hello.proto ;紧接着是服务端代码, ctx_service.go:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net"
    	"net/rpc"
    	"rpc_protobuf/proto"
    )
    
    type HelloServiceCtx struct {
    	conn net.Conn
    	isLogin bool
    }
    
    func (p *HelloServiceCtx) Login(request *proto.String, reply *proto.String) error {
    	if request.GetValue() != "user:password" {
    		return fmt.Errorf("auth failed")
    	}
    	log.Println("login OK")
    	p.isLogin = true
    	return nil
    }
    
    func (p *HelloServiceCtx) Hello(request *proto.String, reply *proto.String) error {
    	if !p.isLogin {
    		return fmt.Errorf("please login")
    	}
    	reply.Value = "hello :"+ reply.GetValue() + ", from " + p.conn.LocalAddr().String()
    	return nil
    }
    
    func main() {
    	listener, err := net.Listen("tcp",":1234")
    	if err != nil {
    		log.Fatal("tcp is error")
    	}
    
    	// 基于每个连接创建一个RPC服务
    	for {
    		conn, err:= listener.Accept()
    		if err != nil {
    			log.Fatal("accept error")
    		}
    		go func() {
    			defer conn.Close()
    			p := rpc.NewServer()
    			p.Register(&HelloServiceCtx{conn:conn})
    			p.ServeConn(conn)
    		}()
    	}
    }
    

    然后是客户端代码ctx_client.go:

    package main
    
    import (
    	"fmt"
    	"log"
    	"net/rpc"
    	"rpc_protobuf/proto"
    )
    
    func main() {
    	// 拨号本端1234端口服务
    	client, err := rpc.Dial("tcp", "localhost:1234")
    	if err != nil {
    		log.Fatal("TCP error:", err)
    	}
    
    	// 统一采用接口提供的参数,和请求参数
    	var reply = &proto.String{}
    	var param = &proto.String{
    		Value: "user:password",
    	}
    
    	// 先登陆后在调服务
    	err = client.Call("HelloServiceCtx.Login", &param, &reply)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	// 调用远程服务
    	err = client.Call("HelloServiceCtx.Hello", &param, &reply)
    	if err != nil {
    		log.Fatal(err)
    	}
    
    	fmt.Println(reply)
    }

    到处RPC和Protobuf相关知识就介绍到这了, 如果想深度研究可以访问官网,之后我们可能会介绍gRPC相关知识。

  • 相关阅读:
    DataImport(译)
    Spring JDBC最佳实践(1)
    在Spring中快速使用EHCache注解
    VS 2010 WPF核心是哪些功能特性 ?
    [你必须知道的.NET]第十五回:继承本质论
    C#设置本地网络(DNS、网关、子网掩码、IP)
    [你必须知道的.NET]第十六回:深入浅出关键字using全接触
    逆变与协变
    C# 判断网站是否能访问或者断链
    接口与抽象类
  • 原文地址:https://www.cnblogs.com/double-W/p/12758491.html
Copyright © 2020-2023  润新知