为应用程序选择许多Internet连接之一

时间:2010-12-28 15:12:20

标签: c# network-programming

我的电脑有几种不同的互联网连接。 LAN,WLAN,WiFi或3G。所有这些都是活动的,机器可以使用它们中的任何一个。

现在我想告诉我的应用程序使用其中一个可用的连接。例如,我想告诉我的应用程序只使用WiFi,而其他软件可能会使用其他东西。

在我的c#应用程序中,我使用HttpWebRequestHttpWebResponse等类。

这甚至可能吗?

4 个答案:

答案 0 :(得分:19)

这是一些先进的功能,它被HttpWebRequest,WebRequest,WebClient等抽象掉。但是,您可以使用TcpClient(使用constructor taking a local endpoint)或使用套接字并调用Socket.Bind来执行此操作。

  

如果需要使用特定的本地端点,请使用Bind方法。您必须先调用Bind才能调用Listen方法。除非需要使用特定的本地端点,否则在使用Connect方法之前无需调用Bind。

绑定到要使用的接口的本地端点。如果您的本地计算机的IP地址为IP地址192.168.0.10,则使用本地端点将强制套接字使用该接口。默认为未绑定(实际为0.0.0.0),它告诉网络堆栈自动解析接口,您要绕过该接口。

以下是一些基于Andrew评论的示例代码。请注意,将0指定为本地端点端口意味着它是动态的。

using System.Net;
using System.Net.Sockets;

public static class ConsoleApp
{
    public static void Main()
    {
        {
            // 192.168.20.54 is my local network with internet accessibility
            var localEndPoint = new IPEndPoint(IPAddress.Parse("192.168.20.54"), port: 0);
            var tcpClient = new TcpClient(localEndPoint);

            // No exception thrown.
            tcpClient.Connect("stackoverflow.com", 80);
        }
        {
            // 192.168.2.49 is my vpn, having no default gateway and unable to forward
            // packages to anything that is outside of 192.168.2.x
            var localEndPoint = new IPEndPoint(IPAddress.Parse("192.168.2.49"), port: 0);
            var tcpClient = new TcpClient(localEndPoint);

            // SocketException: A socket operation was attempted to an unreachable network 64.34.119.12:80
            tcpClient.Connect("stackoverflow.com", 80);
        }
    }
}

答案 1 :(得分:10)

请参阅此MSDN blog entry on ServicePoint.BindIPEndPointDelegate。它解释了如何显式创建将由HttpWebRequest使用的本地端点。

例如,要绑定到192.168.16.100:

WebRequest webReq = WebRequest.Create(myUri);
HttpWebRequest httpRequest = (HttpWebRequest)webReq;
httpRequest.ServicePoint.BindIPEndPointDelegate =
    new BindIPEndPoint(BindIPEndPointCallback);

...

private static IPEndPoint BindIPEndPointCallback(ServicePoint servicePoint,
                                                    IPEndPoint remoteEndPoint,
                                                    int retryCount)
{
    if (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork)
    {
        return new IPEndPoint(IPAddress.Parse("192.168.16.100"), 0);
    }
    // Just use the default endpoint.
    return null;
}

答案 2 :(得分:1)

你绝对可以做到:

Uri uri = new Uri(url, UriKind.Absolute);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);

ServicePoint servicePoint = ServicePointManager.FindServicePoint(uri);
servicePoint.BindIPEndPointDelegate = new BindIPEndPoint(Bind);

//execute the request
response = (HttpWebResponse)request.GetResponse();
Stream receiveStream = response.GetResponseStream();
你可能需要这个:

private IPEndPoint Bind(ServicePoint servicePoint, IPEndPoint remoteEndPoint, int retryCount)
    {
        IPAddress address = IPAddress.Parse(GetHostIP());
        return new IPEndPoint(address, 0);
    }

获取特定适配器的IP:

private string GetIPfromNetworkCard(string EthernetCardName)
    {
        string Ret = "";

        foreach (NetworkInterface netif in NetworkInterface.GetAllNetworkInterfaces())
        {
            if (netif.Name == EthernetCardName)
            {
                IPInterfaceProperties properties = netif.GetIPProperties();

                //foreach (IPAddressInformation unicast in properties.UnicastAddresses)
                //{

                // Select the first one...
                Ret = properties.UnicastAddresses[0].Address.ToString();
                break;

                //}
            }

        }

        return Ret;
    }

答案 3 :(得分:0)

不能使用任何C#类 - 它们都在一个太高的级别运行,它在TCP / IP级别(甚至套接字太高级别)。 Windows TCP / IP堆栈使用路由表和接口度量标准来确定将数据包发送出去的接口。

您可以通过调用GetBestInterfaceEx()来查看Windows TCP / IP堆栈确定哪个接口具有最佳路由(将用于发送数据包的路由)。

在前雇主,我们尝试做类似的事情,通过将套接字绑定到我们想要发送流量的卡的IP地址,将流量分成不同的NIC。但是,Windows会将流量发送到它看到的具有最佳路由的NIC(具有与源不同的IP地址的NIC)。在我们弄清楚发生了什么之前,我们有点头疼。

没有用原始套接字或libpcap(可能是嘲笑,你必须构建自己的TCP / IP和HTTP处理程序)做某事(或许),你不能在Windows上做到这一点。