当前位置: 首页 > 知识库问答 >
问题:

使用计算机名时gRPC DNS解析失败

龚振
2023-03-14

我是gRPC的新手,正在尝试使用cactuaroid中的聊天服务器/客户端示例来学习它。我修改了代码,以显示WPF应用程序中长时间运行的任务的进度。所有代码都在.NET5上运行,我使用的是最新版本的gRPC软件包。

使用计算机的IP地址时,该过程工作正常,但是当为gRPC客户端使用计算机名称时,我收到“DNS解析失败”异常(计算机名称为“skylake”):

RpcException: Status(StatusCode=“Unavailable”, Detail=“DNS 解析 failed for service: skylake:6001”, DebugException=“Grpc.Core.Internal.CoreErrorDetailException: {”created“:”@1615312867.300000000“,”description“:”Resolver transient failure“,”file“:”......\src\core\ext\filters\client_channel\client_channel.cc“,”file_line“:2138,”referenced_errors“:[{”created“:”@1615312867.300000000“,”description“:”DNS 解析失败服务: skylake:6001“,”file“:”......\src\core\ext\filters\client_channel\resolver\dns\c_ares\dns_resolver_ares.cc“,”file_line“:362,”grpc_status“:14,”referenced_errors“:[{”created“:”@1615312867.300000000“,”description“:”C-ares status is not ARES_SUCCESS qtype=AAAA name=skylake is_balancer=0: 無法聯繫 DNS 伺服器“,”file“:”......\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_wrapper.cc“,“file_line”:716,“referenced_errors”:[{“created”:“@1615312866.142000000”,“description”:“C-ares status is not ARES_SUCCESS qtype=A name=skylake is_balancer=0: Can not contact DNS servers”,“file”:“......\src\core\ext\filters\client_channel\resolver\dns\c_ares\grpc_ares_wrapper.cc”,“file_line”:716}]}]}]}]}“)

我用telnet skylake 6001验证了我可以到达端口。我在本地测试,客户端和服务器都在同一台机器上。奇怪的是,gRPC服务器似乎对计算机名没有问题。只是客户对它有意见。

服务器代码:

[Export(typeof(IService))]
    public class ProgressServiceGrpcServer : Progress.ProgressBase, IService
    {
        [Import]
        private Logger m_logger = null;

        [Import]
        private ProgressService m_progressService = null;
        private readonly Empty m_empty = new Empty();

        private const int Port = 6001;
        private readonly Grpc.Core.Server m_server;

        public ProgressServiceGrpcServer()
        {
            m_server = new Grpc.Core.Server
            {
                Services =
                {
                    Progress.BindService(this)
                        .Intercept(new IpAddressAuthenticator())
                },
                Ports =
                {
                    new ServerPort("skylake", Port, ServerCredentials.Insecure)
                }
            };
        }

        public void Start()
        {
            m_server.Start();
            m_logger.Info("Started.");
        }

        public override async Task Subscribe(ChannelName channelName, IServerStreamWriter<ProgressReport> responseStream, ServerCallContext context)
        {
            context.CancellationToken.Register(() => m_logger.Info($"{context.Host} cancels subscription."));

            try
            {
                await m_progressService.GetProgressReportsAsObservable(channelName)
                    .ToAsyncEnumerable()
      .ForEachAwaitAsync(async (x) => await responseStream.WriteAsync(x), context.CancellationToken)
                    .ConfigureAwait(false);
            }
            catch (TaskCanceledException)
            {
                m_logger.Info($"{context.Host} unsubscribed.");
            }
        }

        public override Task<Empty> Write(ProgressReport request, ServerCallContext context)
        {
            m_logger.Info($"{context.Host} {request}");
            m_progressService.Add(request);
            return Task.FromResult(m_empty);
        }
    }

客户端代码:

public class ProgressServiceClient
    {
        private readonly Progress.ProgressClient m_client =
            new Progress.ProgressClient(
                new Channel("skylake”, 6001, ChannelCredentials.Insecure));

        public async Task Write(ProgressReport progressReport)
        {
            await m_client.WriteAsync(progressReport);
        }

        public IAsyncEnumerable<ProgressReport> ProgressReports(ChannelName channelName)
        {
            var call = m_client.Subscribe(channelName);

            return call.ResponseStream
                .ToAsyncEnumerable()
                .Finally(() => call.Dispose());
        }
    }

写入方法的进展:

while (inProgress)
            {
                progressServiceClient.Write(new GrpcServer.ProgressReport
                {
                    Id = Task.Id.ToString(),
                    PercentDone = percentDone,
                    TimeRemain = timeRemain
                }).Wait();

                Thread.Sleep(500);
            }

进度读取方法:

m_progressService = new ProgressServiceClient();
ChannelName channelName = new ChannelName() { Id = id };

var cts = new CancellationTokenSource();
            _ = m_progressService.ProgressReports(channelName)
                .ForEachAsync((x) =>
                {
                    Log.Debug($"id: {x.Id} progress: {x.PercentDone}");
                }, cts.Token);

            this.Dispatcher.Invoke(() =>
            {
                Application.Current.Exit += (_, __) => cts.Cancel();
                this.Unloaded += (_, __) => cts.Cancel();
            });

共有1个答案

富勇军
2023-03-14

感谢@jdweng为我指出了正确的方向,这个问题通过在主机名后面添加DNS后缀(在我的例子中是skylake.lan)得到了解决。我们可以通过ipinterfaceproperties . DNS suffix获得DNS后缀。

或者,(这可能更安全)我们可以通过使用类似的东西来使用正确的IP地址而不是主机名。

 类似资料:
  • 我已经检查了关于同一问题的大多数主题,但我找不到解决方案。 我的应用程序使用连接到一个服务,当我使用托管该服务的机器的IP地址时,它工作正常。但是,当我用主机名替换它时,它无法连接。我使用的连接方法非常标准: 例外情况是: JAVA网。UnknownHostException:无法解析主机“myHostname”:没有与主机名关联的地址 myHostname是我的实际主机名。 当我在我的电脑上使用

  • 我有一个评估csv文件的语法,它根据TestRig正常工作。将生成以下解析树: 但是,如果我在应用程序中使用以下java代码,解析将失败,并出现错误: 更新:我现在直接从文件中使用Char流,但错误仍然存在。 我的理解是,TestRig也会这样做,那么这怎么可能成功,而这怎么可能失败呢? 下面是测试。我用来测试的csv: 至于我如何调用TestRig,我使用命令行: 更新:使用时 我也有同样的错误

  • 问题内容: 我想知道是否有一种方法可以用Java获取计算机名称?我已经看到了该功能的几个答案。但是我想知道是否存在不使用网络的方法? (作为一个附带的问题,计算机名称是否仍然只是一个网络事物,因此必须以这种方式进行??) 问题答案: 操作系统的基础DNS(域名系统)库从IP地址 解析 计算机“名称”。跨操作系统没有通用的计算机名称概念,但DNS通常可用。如果尚未配置计算机名称,以便DNS可以解析它

  • 我建立了一个tic_tac_toe(板)游戏对AI电脑播放器在java,我写了一个MiniMax算法的电脑 下面是我写的MiniMax算法: eval函数是用来计算网格的,我只是把它做成一个例子,下面是函数: 有人知道为什么会这样吗? 函数将获取此棋盘,并通过查找棋盘中的第一个空字符并放置“X”或“O”来尝试查找此棋盘的所有可能移动,这取决于玩家的回合,并返回新棋盘的列表,代码如下。

  • 我有一个gRPC客户端调用同一台机器上的服务器,并且客户端代码使用使用以下创建的通道: 这很有效,我得到了预期的回复。 但是,如果我将“localhost”替换为实际的机器名称(FQDN)或IP地址,我会收到一个错误: 我还测试了在远程机器上启动服务器,并在创建通道时让客户端调用该远程机器(通过名称或IP),但遇到了同样的失败。该应用程序是用C#编写的。NET Core 3.2作为控制台应用程序。