FreeSWITCH及VOIP,Openser,电话机器人等产品中文技术资讯、交流、沟通、培训、咨询、服务一体化网络。QQ群:293697898
QQ群:protobuf-gRPC学习群 298735073
今天遇到一个网友说go lang 的grpc怎么用?按网上的总有问题,好吧,我就再试试go lang的grpc,毕竟有段时间不用它了!
go get google.golang.org/grpc
最好还是先手工把c++的protobuf 3.x的源码编译下,我是win 10 64位,采用cmake生成sln后,由vs2010就编译好了,然后把生成的含protoc.exe的路径添加到path中,然后:
go get -u github.com/golang/protobuf/{proto,protoc-gen-go}
于是乎就可以生成grpc的东东了,我们的proto文件如下,helloworld.proto,这个文件是放在了%GOPATH%\src\grpc\xcl下:
```
syntax = "proto3";
package xcl;
enum UserStatus {
OFFLINE = 0;
ONLINE = 1;
}
message UserInfo {
int32 id = 1;
string name = 2;
UserStatus status = 3 ;
}
message UserID {
int32 id = 1;
}
message funcResponse {
string reply = 1;
}
service UserService {
rpc Login(UserInfo) returns (funcResponse){};
rpc logout(UserID) returns (funcResponse){};
}
```
进入cmd后,
protoc --go_out=plugins=grpc:. helloworld.proto
就会有helloworld.pb.go文件生成
```
package main
import (
pb "grpc/xcl"
"log"
"net"
"os"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
func main() {
log.SetOutput(os.Stdout)
lis, err := net.Listen("tcp", port)
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterUserServiceServer(s, &server{})
log.Println("Server......")
s.Serve(lis)
}
const (
port = ":50051"
)
type server struct{}
func (s *server) Login(ctx context.Context, usr *pb.UserInfo) (*pb.FuncResponse, error) {
log.Println("Server...... Login() UserInfo:", usr)
usr.Id = 100
strId := "100" //strconv.Itoa(usr.Id)
return &pb.FuncResponse{Reply: strId}, nil
}
func (s *server) Logout(ctx context.Context, uid *pb.UserID) (*pb.FuncResponse, error) {
log.Println("Server...... Logout() UserID:", uid)
return &pb.FuncResponse{Reply: "Logout Successed."}, nil
}
```
```
package main
import (
"log"
"os"
"strconv"
pb "grpc/xcl"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
const (
address = "127.0.0.1:50051"
)
func main() {
log.SetOutput(os.Stdout)
conn, err := grpc.Dial(address, grpc.WithInsecure())
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewUserServiceClient(conn)
var status pb.UserStatus
status = pb.UserStatus_ONLINE
userInfo := &pb.UserInfo{
//Id: 10, //proto.Int32(10),
Name: "XCL-gRPC", //proto.String("XCL-gRPC"),
Status: status,
}
r, err := c.Login(context.Background(), userInfo)
if err != nil {
log.Fatalf("登录失败! %v", err)
}
log.Println("Login():", r)
uid, err := strconv.ParseInt(r.Reply, 10, 32)
if err != nil {
log.Fatalf("非数字 %v", err)
}
userID := &pb.UserID{int32(uid)}
out, err := c.Logout(context.Background(), userID)
log.Println("Logout():", out)
}
```
这两个可以是任意处置,我是放在了 %GOPATH%\src\grpc
cmd a: go build server.go 生成server.exe
cmd b: go build client.go 生成client.exe
再分别运行,那么就可以看到
server.exe一直在监听,client.exe出现了
```
2017/01/20 21:09:46 Login(): reply:"100"
2017/01/20 21:09:46 Logout(): reply:"Logout Successed."
```
特别要注意,client.go 下 dial 时,要指定 conn, err := grpc.Dial(address, grpc.WithInsecure()),这也是之前的小兄弟遇到的问题,会异常为:
did not connect: grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)