下面是一个使用golang的gRPC编写的简单示例,展示了客户端向服务端发送心跳的过程:
首先,我们需要定义一个gRPC服务的.proto文件,例如heartbeat.proto:
syntax = "proto3";
package heartbeat;
service HeartbeatService {
rpc SendHeartbeat (HeartbeatRequest) returns (HeartbeatResponse) {}
}
message HeartbeatRequest {
string message = 1;
}
message HeartbeatResponse {
string reply = 1;
}
然后,使用protoc
工具生成gRPC代码:
protoc --go_out=. --go-grpc_out=. heartbeat.proto
接下来,我们可以编写gRPC客户端和服务端的代码。
客户端代码(heartbeat_client.go):
package main
import (
"context"
"log"
"time"
"google.golang.org/grpc"
pb "path/to/heartbeat" // 根据实际的包路径进行修改
)
func main() {
// 连接到gRPC服务端
conn, err := grpc.Dial("localhost:50051", grpc.WithInsecure())
if err != nil {
log.Fatalf("failed to connect: %v", err)
}
defer conn.Close()
// 创建gRPC客户端
client := pb.NewHeartbeatServiceClient(conn)
// 发送心跳
for {
// 创建心跳请求
req := &pb.HeartbeatRequest{
Message: "Heartbeat",
}
// 调用服务端的SendHeartbeat方法
resp, err := client.SendHeartbeat(context.Background(), req)
if err != nil {
log.Printf("failed to send heartbeat: %v", err)
} else {
log.Printf("received reply: %s", resp.Reply)
}
// 等待一段时间后再发送心跳
time.Sleep(5 * time.Second)
}
}
服务端代码(heartbeat_server.go):
package main
import (
"context"
"log"
"net"
"google.golang.org/grpc"
pb "path/to/heartbeat" // 根据实际的包路径进行修改
)
type server struct {
pb.UnimplementedHeartbeatServiceServer
}
func (s *server) SendHeartbeat(ctx context.Context, req *pb.HeartbeatRequest) (*pb.HeartbeatResponse, error) {
log.Printf("received heartbeat: %s", req.Message)
// 创建心跳响应
resp := &pb.HeartbeatResponse{
Reply: "Heartbeat received",
}
return resp, nil
}
func main() {
// 监听端口
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
// 创建gRPC服务
s := grpc.NewServer()
// 注册服务实现
pb.RegisterHeartbeatServiceServer(s, &server{})
// 启动服务
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
在上面的示例中,我们创建了一个HTTP处理函数handleWebSocket
来处理WebSocket连接。当客户端发起WebSocket连接时,我们使用upgrader.Upgrade
函数将HTTP连接升级为WebSocket连接。
在handleWebSocket
函数中,我们使用conn.ReadMessage
读取客户端发送的消息,并使用fmt.Println
打印消息内容。然后,我们使用conn.WriteMessage
发送确认消息给客户端。
这个示例只是一个简单的消息确认机制的演示,你可以根据自己的需求进行扩展和改进。例如,你可以在客户端发送消息时添加一个唯一的标识符,服务端收到消息后,可以将确认消息与原始消息关联起来,以便进行更精确的确认。
希望这个示例对你有帮助!如果你有任何其他问题,请随时提问。