Sending HttpWebRequest through a specific network

2019-01-19 00:21发布

问题:

I have two wireless network adapters connected to my computer, each connected to a different network. I would like to build a kind of proxy server that my browser would connect to and it will send HTTP requests each from different adapter so loading time on webpages would be smaller. Do you guys know how can I decide from which network adapter to send the HttpWebRequest?

Thanks :)

UPDATE

I used this code:

public static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
{
    List<IPEndPoint> ipep = new List<IPEndPoint>();
    foreach (var i in System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces())
    {
        foreach (var ua in i.GetIPProperties().UnicastAddresses)
            ipep.Add(new IPEndPoint(ua.Address, 0));
    }
    return new IPEndPoint(ipep[1].Address, ipep[1].Port);
}

private void button1_Click(object sender, EventArgs e)
{
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://whatismyip.com");
    request.ServicePoint.BindIPEndPointDelegate = new BindIPEndPoint(BindIPEndPointCallback);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    StreamReader sr = new StreamReader(response.GetResponseStream());
    string x = sr.ReadToEnd();
}

But even if a change the IPEndPoint I send the IP I get from WhatIsMyIp is still the same.. any help?

回答1:

BindIPEndPointDelegate may well be what you're after here. It allows you to force a particular local IP to be the end-point via which the HttpWebRequest is sent.



回答2:

This example works for me:

using System;
using System.Net;

class Program
{
    public static void Main ()
    {
        foreach (var ip in Dns.GetHostAddresses (Dns.GetHostName ())) 
        {
            Console.WriteLine ("Request from: " + ip);
            var request = (HttpWebRequest)HttpWebRequest.Create ("http://ns1.vianett.no/");
            request.ServicePoint.BindIPEndPointDelegate = delegate {
                return new IPEndPoint (ip, 0);
            };
            var response = (HttpWebResponse)request.GetResponse ();
            Console.WriteLine ("Actual IP: " + response.GetResponseHeader ("X-YourIP"));
            response.Close ();
        }
    }
}


回答3:

This is because WebRequest uses ServicePointManager and it caches actual ServicePoint that is been used for single URI. So in your case BindIPEndPointDelegate called only once and all subsequent CreateRequest reuses same binded interface. Here is a little bit more lower level example with TcpClient that actually works:

        foreach (var iface in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (iface.OperationalStatus == OperationalStatus.Up && iface.NetworkInterfaceType != NetworkInterfaceType.Loopback)
            {
                Console.WriteLine("Interface: {0}\t{1}\t{2}", iface.Name, iface.NetworkInterfaceType, iface.OperationalStatus);
                foreach (var ua in iface.GetIPProperties().UnicastAddresses)
                {
                    Console.WriteLine("Address: " + ua.Address);
                    try
                    {
                        using (var client = new TcpClient(new IPEndPoint(ua.Address, 0)))
                        {
                            client.Connect("ns1.vianett.no", 80);
                            var buf = Encoding.UTF8.GetBytes("GET / HTTP/1.1\r\nConnection: close\r\nHost: ns1.vianett.no\r\n\r\n");
                            client.GetStream().Write(buf, 0, buf.Length);
                            var sr = new StreamReader(client.GetStream());
                            var all = sr.ReadToEnd();
                            var match = Regex.Match(all, "(?mi)^X-YourIP: (?'a'.+)$");
                            Console.WriteLine("Your address is " + (match.Success ? match.Groups["a"].Value : all));
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }