gpt4 book ai didi

c# - SSL gRPC 客户端在 C# 中工作正常,但在 C++ 中因 UNAVAILABLE "Empty update"而失败

转载 作者:行者123 更新时间:2023-12-04 22:36:55 24 4
gpt4 key购买 nike

在带有 VS2022 17.1.2 和 .NET 6 的 Windows 10 Pro 21H2 上,我正在将一个简单的 C# gRPC 客户端移植到 C++,但是尽管我的代码似乎在做同样的事情,但 C++ 客户端总是无法连接到服务器,而且我用完了想法为什么。
我的 gRPC 服务器使用 SSL 和 LetsEncrypt 生成的证书(通过 LettuceEncrypt),因此我使用默认 SslCredentials .
在 C#(带有 Grpc.Core )中,我使用 gRPC 如下:

// Channel and client creation
var channel = new Channel("my.domain.org:12345", new SslCredentials());
var client = new MyGrpc.MyGrpcClient(channel);
// Sample call
LoginUserReply reply = client.LoginUser(new LoginUserRequest()
{
Username = username
});
我将其转换为 C++ 如下,主要基于 gRPC 网站上给出的示例:
// Channel and client creation
auto channelCreds = SslCredentials(SslCredentialsOptions());
auto channel = CreateChannel("my.domain.org:12345", channelCreds);
auto stub = MyGrpc::NewStub(channel);
// Sample call
ClientContext context;
LoginUserRequest request;
request.set_username(username);
LoginUserReply reply;
Status status = m_stub->LoginUser(&context, request, &reply);
但是,在 C++ 中使用这样的代码, status总是以 UNAVAILABLE (14) "Empty update"报告失败。
为什么会这样,我该如何解决?

到目前为止我所做的调查:
  • 仅使用 InsecureChannelCredentials()导致 UNAVAILABLE (14) “无法连接到所有地址”。
  • 以纯文本方式运行服务器,调用 OK (0) 仅用于测试目的(由 Lei Yang 建议)。
  • 我设置GRPC_TRACE=allGRPC_VERBOSITY=DEBUG环境变量,但没有看到来自客户端的额外日志记录。
  • 在 C# 服务器中,我将 Grpc 日志记录级别设置为调试,并且只注意到没有像工作/未加密的客户端一样获得“正在读取消息”日志行。
  • 最佳答案

    这是 known issue在 gRPC 客户端的 Windows C++ 实现中(显然也是 macOS)。 gRPC authentication guide上有一个小注释说明:

    Non-POSIX-compliant systems (such as Windows) need to specify the root certificates in SslCredentialsOptions, since the defaults are only configured for POSIX filesystems.


    因此,要在 Windows 上实现此功能,您需要填充 SslCredentialsOptions如下:
    #include <wincrypt.h>

    SslCredentialsOptions getSslOptions()
    {
    // Fetch root certificate as required on Windows (s. issue 25533).
    SslCredentialsOptions result;

    // Open root certificate store.
    HANDLE hRootCertStore = CertOpenSystemStoreW(NULL, L"ROOT");
    if (!hRootCertStore)
    return result;

    // Get all root certificates.
    PCCERT_CONTEXT pCert = NULL;
    while ((pCert = CertEnumCertificatesInStore(hRootCertStore, pCert)) != NULL)
    {
    // Append this certificate in PEM formatted data.
    DWORD size = 0;
    CryptBinaryToStringW(pCert->pbCertEncoded, pCert->cbCertEncoded,
    CRYPT_STRING_BASE64HEADER, NULL, &size);
    std::vector<WCHAR> pem(size);
    CryptBinaryToStringW(pCert->pbCertEncoded, pCert->cbCertEncoded,
    CRYPT_STRING_BASE64HEADER, pem.data(), &size);

    result.pem_root_certs += utf8Encode(pem.data());
    }

    CertCloseStore(hRootCertStore, 0);
    return result;
    }
    如果您需要 utf8Encode方法也是:
    std::string utf8Encode(const std::wstring& wstr)
    {
    if (wstr.empty())
    return string();

    int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
    NULL, 0, NULL, NULL);
    std::string strTo(sizeNeeded, 0);
    WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(),
    &strTo[0], sizeNeeded, NULL, NULL);
    return strTo;
    }
    有一个(可悲的是不断陈旧) feature request在 gRPC 存储库上添加对 Windows 的开箱即用支持以及使默认行为 SslCredentials()在所有系统上都一样。

    关于c# - SSL gRPC 客户端在 C# 中工作正常,但在 C++ 中因 UNAVAILABLE "Empty update"而失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71580681/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com