國內網路問題,windows使用grpc程序
安裝protoc
將寫好的proto檔案,生成pb.go檔案,下載地址https://github.com/protocolbuffers/protobuf/releases,下載下來的是一個zip檔案,將檔案解壓找到/bin/protoc.exe,將其配置到環境變數,在控制臺中輸入protoc --version,列印出下載protoc版本說明安裝正確,

安裝grpc
這里因為網路問題,需要從github上拉原始碼安裝,
git clone https://github.com/golang/net.git %GOPATH%/src/golang.org/x/net
git clone https://github.com/golang/text.git %GOPATH%/src/golang.org/x/text
git clone https://github.com/grpc/grpc-go.git %GOPATH%/src/google.golang.org/grpc
git clone https://github.com/protocolbuffers/protobuf-go.git %GOPATH%/src/google.golang.org/protobuf
git clone https://github.com/google/go-genproto.git %GOPATH%/src/google.golang.org/genproto
這里是grpc依賴的,已經編譯時依賴的全部資源
安裝protoc-gen-go
go get github.com/golang/protobuf/protoc-gen-go
我這里使用的是protoc-gen-gofast(有大佬做過測驗,go-fast要快4-7倍,https://studygolang.com/articles/22824)
使用原始碼安裝
git clone https://github.com/gogo/protobuf.git
go install protoc-gen-gofast
至此準備作業已經完成,接下來進行簡單的測驗
Grpc測驗
grpc基于http2.0,再次同時記錄一下grpc流模式的使用(http2.0 :1. 多路復用 2.TCP連接 3.二進制代替文本 4.標題壓縮 5.服務器推送,grpc也同樣具有這些功能)
proto檔案
syntax = "proto3";
package proto;
option go_package = "proto";
message HelloReq {
string name = 1;
string content = 2;
}
message HelloResp{
string content = 1;
}
message HelloListResp{
repeated string content = 1;
}
service HelloService {
// 普通呼叫
rpc Hello(HelloReq) returns (HelloResp){}
// 客戶端流模式
rpc HelloClientStream(stream HelloReq) returns (HelloListResp){}
// 服務端流模式
rpc HelloServerStream(HelloReq) returns (stream HelloResp){}
// 雙向流模式
rpc HelloStream(stream HelloReq) returns (stream HelloResp){}
}
在proto檔案的目錄下執行 protoc --gofast_out=plugins=grpc:. *.proto 生成 hello.pb.go 檔案,
服務端代碼:
package main
import (
"context"
"demo/proto"
"fmt"
"google.golang.org/grpc"
"io"
"net"
)
type HelloServer struct {
}
func (*HelloServer) Hello(ctx context.Context, in *proto.HelloReq) (*proto.HelloResp, error) {
return &proto.HelloResp{
Content: fmt.Sprintf("%v : %v", in.GetName(), in.GetContent()),
}, nil
}
func (*HelloServer) HelloClientStream(stream proto.HelloService_HelloClientStreamServer) error {
var users []string
for {
recv, err := stream.Recv()
//接收完了回傳結果并關閉
if err == io.EOF {
return stream.SendAndClose(&proto.HelloListResp{
Content: users,
})
}
if err != nil {
return err
}
users = append(users, fmt.Sprintf(recv.GetName()+" : "+recv.GetContent()))
}
}
func (*HelloServer) HelloServerStream(in *proto.HelloReq, stream proto.HelloService_HelloServerStreamServer) error {
for i := 0; i < 10; i++ {
stream.Send(&proto.HelloResp{
Content: fmt.Sprintf("%v - %v : %v", i, in.GetName(), in.GetContent()),
})
}
return nil
}
func (*HelloServer) HelloStream(stream proto.HelloService_HelloStreamServer) error {
for {
recv, err := stream.Recv()
//接收完了回傳
if err == io.EOF {
return nil
}
if err != nil {
return err
}
err = stream.Send(&proto.HelloResp{
Content: fmt.Sprintf("%v : %v", recv.GetName(), recv.GetContent()),
})
if err != nil {
return err
}
}
}
func main() {
listen, err := net.Listen("tcp", ":8001")
if err != nil {
panic(err)
}
s := grpc.NewServer()
proto.RegisterHelloServiceServer(s, &HelloServer{})
err = s.Serve(listen)
if err != nil {
panic(err)
}
}
客戶端實作:
package main
import (
"context"
"demo/proto"
"fmt"
"google.golang.org/grpc"
"io"
"strconv"
"time"
)
func main() {
conn, err := grpc.Dial("localhost:8001", grpc.WithInsecure(), grpc.WithBlock())
if err != nil {
panic(err)
}
defer conn.Close()
cli := proto.NewHelloServiceClient(conn)
// 普通呼叫
hello, err := cli.Hello(context.Background(), &proto.HelloReq{
Name: "demo",
Content: "Hello World",
})
if err != nil {
panic(err)
}
fmt.Println(hello.GetContent())
// 客戶端流模式測驗
client, err := cli.HelloClientStream(context.Background())
if err != nil {
panic(err)
}
for i := 0; i < 5; i++ {
client.Send(&proto.HelloReq{
Name: "world" + strconv.Itoa(i),
Content: "hello",
})
}
client.CloseSend()
recv, err := client.CloseAndRecv()
if err != nil {
panic(err)
}
for i := range recv.Content {
fmt.Println(recv.GetContent()[i])
}
// 服務端流模式測驗
stream, err := cli.HelloServerStream(context.Background(), &proto.HelloReq{
Name: "hello",
Content: "world",
})
for {
resp, err := stream.Recv()
if err != nil {
if err == io.EOF {
break
} else {
panic(err)
}
}
fmt.Println(resp.Content)
}
// 雙向流模式測驗
helloStream, err := cli.HelloStream(context.Background())
if err != nil {
panic(err)
}
go func() {
for {
resp, err := helloStream.Recv()
if err != nil {
if err == io.EOF {
break
} else {
panic(err)
}
}
fmt.Println(resp.Content)
}
}()
for i := 0; i < 5; i++ {
time.Sleep(time.Second)
fmt.Println("send", i)
helloStream.Send(&proto.HelloReq{
Name: "hello" + strconv.Itoa(i),
Content: "world",
})
}
helloStream.CloseSend()
time.Sleep(time.Second)
}
目錄結構如下:

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/278128.html
標籤:區塊鏈
