Matt
Matt

Reputation: 160

Xamarin.Forms and gRPC. "failed to connect to all addresses" error message

I'm struggling to get a gRPC client built with Xamarin.Forms to communicate with a gRPC server running on my localhost. The server can be reached without issue with BloomRPC, however I can't seem to get it to work properly from my client. The server is listening on http://localhost:5000 and https://localhost:5001.

I initially thought that perhaps it was because it's running on localhost that my client is struggling, so I also tried using a RemoteURL courtesy of Conveyor by Keyoti, which is set to http://192.168.1.64:45455 and https://192.168.1.64:45456, however I'm not quite sure how that works with my gRPC server as it is specifically listening on ports 5000 and 5001. Either way, trying to connect by either method results in an RPCException stating "failed to connect to all addresses".

I'm using the Grpc.Core library, and Grpc.Core.Xamarin (version 2.41.1) with the below code. I've also tried using version 1.20.1, but without success. The below code tries to connect to the authentication service which simply returns a GUID.

public static async Task<Msg.SessionTokenResponse> test()
{
    // I've also tried, localhost:5000, localhost:5001 (with and without SSL credentials), 
    // 127.0.0.1:5001 (with and without SSL credentials), 0.0.0.0:5000, 0.0.0.0:5001 
    // (with and without SSL credentials), 192.168.1.64:45455, 192.168.1.64:45456 (with and 
    // without SSL credentials)
    var channel = new Channel("127.0.0.1:5000", ChannelCredentials.Insecure);

    var client = new AuthenticationService.AuthenticationServiceClient(channel);
    var request = new Msg.SessionTokenRequest();

    try
    {
        return await client.CreateSessionTokenAsync(request);
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.Message);
        throw ex;
    }
    finally
    {
        await channel.ShutdownAsync();
    }
}

It's also worth noting if I try to pass http:// or https:// at the start of the address I get a "DNS resolution failed for service" error message. Upon reading up it looks like this is not meant to be provided as part of the address, but I may be misunderstanding the requirements. I have tried this with my firewall disabled, and have no proxy. I've also tried adding the following environment variables:

Environment.SetEnvironmentVariable("NO_PROXY", "127.0.0.1");
Environment.SetEnvironmentVariable("GRPC_DNS_RESOLVER", "native");
Environment.SetEnvironmentVariable("GRPC_VERBOSITY", "debug");
Environment.SetEnvironmentVariable("GRPC_TRACE", "all");

I can't see anything helpful in the logging.

Any and all help would be greatly appreciated.

Upvotes: 0

Views: 1181

Answers (1)

Matt
Matt

Reputation: 160

After all the help from @Jason I was finally able to get this resolved.

As he alluded to, the problem was because the code is running on the simulators, not my local machine (even if the simulators are on my local machine), and thus referring to localhost will simply try to access the simulator, not my PC.

To get around this without publishing my gRPC server to some other device, I simply needed to change the applicationUrl in my gRPC server's launchSettings.json file so that it would listen specifically to my internal IP address, and not localhost. My launchSettings.json file looks like below:

{
  "profiles": {
    "MyGRPCServer.API": {
      "commandName": "Project",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      },
      "applicationUrl": "https://192.168.1.64:45456;http://192.168.1.64:45455"
    }
  }
}

I then simply whitelisted ports 45455 and 45456 in my firewall and the simulators were able to access my gRPC server.

I also changed

var channel = new Channel("127.0.0.1:5000", ChannelCredentials.Insecure);

to

var channel = new Channel("192.168.1.64:45455", ChannelCredentials.Insecure);

Thanks again for all the help Jason, and hopefully this helps someone else.

Upvotes: 1

Related Questions