如何使用 gRPC 在客户端和服务器之间双向发送和接收流元数据?

How can I send and receive stream meta-data bidirectionally between client and server with gRPC?

我想使用 gRPC 将文件从客户端传输到服务器,并将文件从服务器传输到客户端。但是,接收进程不知道要接收多少字节。我看到有人建议将其附加到正在传输的数据的头部,然后在从流中接收到第一个块时将其解析出来。但是,如果可能的话,我想避免这种情况。在 gRPC C++ API 中,我看到 ClientWriter 实现了 ClientStreamingInterface 并且可以使用 WaitForInitialMetadata() 访问服务器元数据。服务器实现 ServerStreamingInterface 并可以使用 SendInitialMetadata() 方法发送服务器元数据。

来自 the documentation 尚不清楚此元数据包含什么以及我如何添加自己的元数据以便我可以在发送之前通知客户端期望从服务器获得的文件大小。

此外,我发现没有简单的方法可以使用 gRPC C++ 通知服务器期望从客户端获得的文件大小 API。

当然,我是 gRPC 和 C++ 的新手,所以任何正确方向的指示都将不胜感激。

这里有一个参考: https://grpc.github.io/grpc/cpp/classgrpc__impl_1_1_client_context.html https://grpc.github.io/grpc/cpp/classgrpc__impl_1_1_server_context.html

这里有一个例子: https://github.com/grpc/grpc/blob/master/examples/cpp/metadata/greeter_server.cc

客户端和服务端都可以分别在ClientContext和ServerContext上指定发送的初始元数据。该方法在 ClientContext 上称为 AddMetadata,在 ServerContext 上称为 AddInitialMetadata(以区分尾随元数据):

    // AddMetadata (const grpc::string &meta_key, const grpc::string &meta_value)
    context->AddMetadata("custom-server-metadata", "initial metadata value");

在这种情况下,值是一个字符串。要指定一个数字,通常您会使用 grpc::to_string:

    context->AddInitialMetadata("filesize", grpc::to_string(file_size));

接收方的元数据格式为

    const std::multimap< grpc::string_ref, grpc::string_ref > &

该类型由ServerContext::client_metadata()(获取客户端在服务器端的初始元数据)和ClientContext::GetServerInitialMetadata()(在WaitForInitialMetadata( ) 已在同步 API 或其他 APIs 中返回。

要查看文件大小,您可以这样做:

    int filesize = atoi(metadata.find("filesize")->second);

(如果您不确定是否指定了 "filesize",您可能需要检查 metadata.find("filesize") != metadata.end())

至于如何发送初始元数据,当您在线上发送 RPC 时,它会在客户端自动发送。在服务器端,您可以使用 SendInitialMetadata() 显式发送它,或者它会与您的第一个服务器写入流。