0

I am trying to specify the local endpoint for some HTTP requests that I need to send.

So, I have multiple IPs on my device (Wifi and Cellular) and would like to chose which one of those I want to use when sending HTTP request to get/post data from the server.

I learned that it is possible with HttpClient with .NET core 5.0 (that isn't supported with Xamarin) HttpClient specify interface to bind to / make requests from

SocketsHttpHandler socketsHttpHandler = new SocketsHttpHandler();
socketsHttpHandler.ConnectCallback = async (context, token) =>
{
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    s.Bind(new IPEndPoint(IPAddress.Loopback, 0));
    await s.ConnectAsync(context.DnsEndPoint, token);
    s.NoDelay = true;
    return new NetworkStream(s, ownsSocket: true);
};

using (HttpClient Client = new HttpClient(socketsHttpHandler))
{
    Client.BaseAddress = new Uri("PutIPHere//");
    HttpResponseMessage Response = await Client.GetAsync("");
    // use Response as needed...
}

Another way is with reflection (but only with .NET framework), see L.B Answer

HttpClientHandler SetServicePointOptions(HttpClientHandler handler)
{
    var field = handler.GetType().GetField("_startRequest", BindingFlags.NonPublic | BindingFlags.Instance); // Fieldname has a _ due to being private
    var startRequest = (Action<object>)field.GetValue(handler);

    Action<object> newStartRequest = obj =>
    {
        var webReqField = obj.GetType().GetField("webRequest", BindingFlags.NonPublic | BindingFlags.Instance);
        var webRequest = webReqField.GetValue(obj) as HttpWebRequest;
        webRequest.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);
        startRequest(obj); //call original action
    };

    field.SetValue(handler, newStartRequest); //replace original 'startRequest' with the one above

    return handler;
}

private static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
{
    return new IPEndPoint(IPAddress.Parse("PutIPHere"), 0);
}

Is there any way to specify the local endpoint for HTTP requests (using Xamarin)? I would like to do it from the PLC, but also native to android and iOS should be ok. Thanks in advance

  • If your `HttpClient` [uses `HttpClientHandler`](https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack), then I believe you could use [`BindIPEndPointDelegate`](https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepoint.bindipendpointdelegate?redirectedfrom=MSDN&view=net-5.0#System_Net_ServicePoint_BindIPEndPointDelegate). – Stephen Cleary Apr 14 '21 at 20:47
  • @StephenCleary Can you add more details please? As I understand it, the property [BindIPEndPointDelegate](https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepoint.bindipendpointdelegate?redirectedfrom=MSDN&view=net-5.0#System_Net_ServicePoint_BindIPEndPointDelegate) is under [ServicePoint](https://learn.microsoft.com/en-us/dotnet/api/system.net.servicepoint?view=net-5.0) and I do not have access to it from [HttpClientHandler](https://learn.microsoft.com/en-us/xamarin/android/app-fundamentals/http-stack?tabs=windows) . Do you have a sample code? – Shlomi Sapir Apr 15 '21 at 06:00
  • You should be able to do `ServicePointManager.FindServicePoint(uri).BindIPEndPointDelegate` to set the delegate for a specific uri/host. – Stephen Cleary Apr 15 '21 at 12:20
  • @StephenCleary It works, thank you. – Shlomi Sapir Apr 15 '21 at 19:15
  • @ShlomiSapir Can you confirm that you made it work by using HttpWebRequest rather than HttpClient please? Here, we need to do the same with HttpClient in our Xamarin Forms application. A library that we use within our app uses HttpClient. Thanks, – Kazutsugu Fukumuro Jan 09 '23 at 10:56

0 Answers0