简体   繁体   中英

How to bind HttpClient to a specific (source) ip address in .NET 5

According to issue #1793 it shouldn't be necessary to use quirks like this to bind a HttpClient in .NET 5 to a specific local ip address.

However, I'm totally overwhelmed by this topic meanwhile where .NET Core developers aren't capable since years to bring the option of chosing the outgoing ip address of a http request to .NET Core. Even the backwards compatible WebClient isn't capable of doing this in earlier .NET Core versions nor any other high level HTTP API is capable of doing this. God (or whoever) praise .NET 5, which should (hopefully?) bring such capabilities back to a modern .NET framework.

How can I configure a HttpClient object to chose a specific local ip address for outgoing connections only using on-bord methods in .NET 5? Or is it still impossible? Bonus question: How can I configure a ClientWebSocket object to chose a specific local ip address for the outgoing connection only using on-bord methods in .NET 5?

In my setup computers have multiple ip addresses and the services I'm accessing have quite strict rate limits based on source ip addresses.

Please refrain from telling me, that the operating system will chose the right adapter or ip address to use. Please don't send me to a 3rd party library. Yes, even if they fixed WebClient in this regard I don't wanna use it.

Other issues of interest:

  • #23267 : HttpClient specify interface to bind to / make requests from
  • #28721 : Add ConnectCallback on SocketsHttpHandler (aka custom Dialers)

.NET Core and therefore also .NET 5 supports various HttpHandler s. The SocketsHttpHandler is used to configure a HttpClient to use the .NET internal socket implementation (not relying on WinHttp).

Since .NET 5 you can use the ConnectCallback of the SocketsHttpHandler to configure how the connection should be established like this:

public static HttpClient GetHttpClient(IPAddress address)
{
    if (IPAddress.Any.Equals(address))
        return new HttpClient();

    SocketsHttpHandler handler = new SocketsHttpHandler();

    handler.ConnectCallback = async (context, cancellationToken) =>
    {
        Socket socket = new Socket(SocketType.Stream, ProtocolType.Tcp);

        socket.Bind(new IPEndPoint(address, 0));

        socket.NoDelay = true;

        try
        {
            await socket.ConnectAsync(context.DnsEndPoint, cancellationToken).ConfigureAwait(false);

            return new NetworkStream(socket, true);
        }
        catch
        {
            socket.Dispose();

            throw;
        }
    };

    return new HttpClient(handler);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM