【发布时间】:2020-05-31 17:39:53
【问题描述】:
我正在尝试从 android 向 gRPC 服务发送请求。使用在同一台计算机上运行的 WPF 网络核心应用程序,它可以工作,但在 android 上它不起作用。我也在另一台计算机(在虚拟机中)尝试过这个 WPF 应用程序,它也可以正常工作。
我的 xamarion 应用程序代码:
private void SetVariablesServicio()
{
_serviceAddress = "http://1.2.3.4:5001";
using (StreamReader miCertificado = new StreamReader(Assets.Open("CA.crt")))
{
_caCertificate = miCertificado.ReadToEnd();
}
using (StreamReader miCertificado = new StreamReader(Assets.Open("Client.crt")))
{
_clientCertificate = miCertificado.ReadToEnd();
}
using (StreamReader miCertificado = new StreamReader(Assets.Open("Client.key")))
{
_clientPrivateKey = miCertificado.ReadToEnd();
}
}
private async void btnTestServicio_Click()
{
try
{
GrpcClient.GestorAplicaciones miGrpcClient = new GrpcClient.GestorAplicaciones(_serviceAddress, _caCertificate, _clientCertificate, _clientPrivateKey);
string miSaludo = await miGrpcClient.PingAsync("Álvaro");
ShowAlert("Error", miSaludo);
}
catch (Exception ex)
{
ShowAlert("Error", ex.Message);
}
}
gRPC 客户端的通用库:
public class GestorAplicaciones
{
#region constructor
public GestorAplicaciones(string paramAddressService, string paramStrCertificadoCa, string paramStrCertificadoCliente, string paramStrClaveCertificadoCliente)
{
_serviceAddress = paramAddressService;
_caCertificate = paramStrCertificadoCa;
_clientCertificate = paramStrCertificadoCliente;
_clientPrivateKey = paramStrClaveCertificadoCliente;
}
#endregion constructor
#region variables de clase
private string _serviceAddress;
private string _caCertificate;
private string _clientPrivateKey;
private string _clientCertificate;
#endregion variables de clase
#region método de llamada al servicio
public async Task<string> PingAsync(string paramStrNombreLlamante)
{
Gestor.GestorClient miClienteGrpc = GetClient();
PingRequest input = new PingRequest { NomreLlamante = paramStrNombreLlamante };
var reply = await miClienteGrpc.PingAsync(input);
return reply.MensajeRespuesta;
}
private Gestor.GestorClient GetClient()
{
var httpClientHandler = new System.Net.Http.HttpClientHandler();
httpClientHandler.ServerCertificateCustomValidationCallback =
System.Net.Http.HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
var httpClient = new System.Net.Http.HttpClient(httpClientHandler);
var channel = GrpcChannel.ForAddress(_serviceAddress,
new GrpcChannelOptions { HttpClient = httpClient });
var client = new Gestor.GestorClient(channel);
return client;
}
WPF 客户端:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
_serviceAddress = "https://1.2.3.4:5001";
_caCertificate = System.IO.File.ReadAllText("certificados/ca.crt");
_clientPrivateKey = System.IO.File.ReadAllText("certificados/client.key");
_clientCertificate = System.IO.File.ReadAllText("certificados/client.crt");
}
#region variables de clase
private readonly string _serviceAddress;
private readonly string _caCertificate;
private readonly string _clientPrivateKey;
private readonly string _clientCertificate;
#endregion variables de clase
private async void Button_Click(object sender, RoutedEventArgs e)
{
try
{
GrpcClient.GestorAplicaciones miGrpcClient = new GrpcClient.GestorAplicaciones(_serviceAddress, _caCertificate, _clientCertificate, _clientPrivateKey);
string miSaludo = await miGrpcClient.PingAsync("Álvaro");
MessageBox.Show(miSaludo);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
服务:
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS, visit https://go.microsoft.com/fwlink/?linkid=2099682
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.ConfigureKestrel(options =>
{
//NOTA: se tiene que poner la IP porque si no, se dice que el equipo remoto ha denegado la conexión.
options.Listen(miAddress, 5001, o =>
{
o.Protocols = HttpProtocols.Http2;
o.UseHttps(@"certificados\service.pfx", "123456");
});
})
.ConfigureLogging(logging =>
{
logging.AddFilter("Grpc", LogLevel.Debug);
});
webBuilder.UseStartup<Startup>();
});
}
我的想法是为客户端提供一个通用库,供 xamarin 和 wpf 客户端使用。
我正在调试将其部署在安卓手机中的 xamarion 应用程序。
为什么请求来自 WPF 应用程序而不是来自 xamarin 应用程序?
谢谢。
【问题讨论】:
-
您是否遇到异常或错误?这些是什么?您是否验证过您的服务器可以从您的 Android 设备访问?您是否已将应用配置为允许非 https 请求?
-
我在 android 设备中安装了一个 ping 应用程序,我得到了响应。我试图不安全的凭据,所以服务是 http 而不是 https,但问题是一样的。无论如何,我想学习如何使用凭证和 SSL 证书。
-
关于 Xamarin.forms 中带有凭据的 https,也许你可以阅读 HTTPS Service With Self-Signed Certificate
-
xamarin 内部使用的 SocketsHttpHandler 似乎是不支持 Http2 的旧版本。您可以使用wireshark 以及通过调查android 上的grpc 通道使用的HttpClient 来看到这一点。
-
stackoverflow.com/questions/60100916/… 我正在解决最近有人在 Stackoverflow 上报告的这个问题。上面的答案似乎不完整。我试图将此调试到 xamarin-android 代码。很难了解它的内部结构,因为它是一个具有复杂依赖关系的大型存储库。如果我设法解决,将发布答案。
标签: c# xamarin xamarin.android grpc