下面是一个使用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发送确认消息给客户端。

这个示例只是一个简单的消息确认机制的演示,你可以根据自己的需求进行扩展和改进。例如,你可以在客户端发送消息时添加一个唯一的标识符,服务端收到消息后,可以将确认消息与原始消息关联起来,以便进行更精确的确认。

希望这个示例对你有帮助!如果你有任何其他问题,请随时提问。