Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/272.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为应用程序选择多个Internet连接中的一个_C#_Network Programming - Fatal编程技术网

C# 为应用程序选择多个Internet连接中的一个

C# 为应用程序选择多个Internet连接中的一个,c#,network-programming,C#,Network Programming,我有一台电脑,有几个不同的网络连接。LAN、WLAN、WiFi或3G。所有这些都处于激活状态,机器可以使用其中任何一个 现在我想告诉我的应用程序使用一个可用的连接。例如,我想告诉我的应用程序只使用WiFi,而其他软件可能使用其他东西 在我的c#应用程序中,我使用了HttpWebRequest和HttpWebResponse之类的类 这可能吗?不可能使用任何C#类-它们都在过高的级别上运行,而不是在TCP/IP级别上运行(即使套接字也过高)。Windows TCP/IP堆栈使用路由表和接口度量来确

我有一台电脑,有几个不同的网络连接。LAN、WLAN、WiFi或3G。所有这些都处于激活状态,机器可以使用其中任何一个

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

在我的c#应用程序中,我使用了
HttpWebRequest
HttpWebResponse
之类的类


这可能吗?

不可能使用任何C#类-它们都在过高的级别上运行,而不是在TCP/IP级别上运行(即使套接字也过高)。Windows TCP/IP堆栈使用路由表和接口度量来确定发送数据包的接口

通过调用,您可以看到Windows TCP/IP堆栈确定的接口具有最佳路由(它将使用该路由发送数据包)

在一位以前的雇主那里,我们试图做类似的事情,通过将套接字绑定到我们想要发送流量的卡的IP地址,将流量分离到不同的NIC上。但是,Windows会将流量发送到它所看到的具有最佳路由的NIC(一个IP地址与源地址不同的NIC)。在我们弄清楚到底发生了什么之前,我们费了点劲


如果不使用原始套接字或libpcap(这很可笑,您必须构建自己的TCP/IP和HTTP处理程序),您就无法在Windows上实现这些功能。

这是一些高级功能,被HttpWebRequest、WebRequest、WebClient等抽象掉了。但是,您可以使用
TcpClient
(使用)或使用套接字和调用来执行此操作

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

绑定到要使用的接口的本地端点。如果您的本地计算机具有用于WiFi地址的ip地址192.168.0.10,则使用该地址的本地端点将强制套接字使用该接口。默认值是unbound(实际上是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);
        }
    }
}
请参阅此MSDN。它解释了如何显式创建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;
}

你绝对可以做到:

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;
    }

若你们连接到互联网,你们可以访问互联网,为什么你们需要告诉你们的家人application@Saurabh也许一条路由比另一条快。这超出了我的知识范围,但你不能在这里用代理做点什么吗?@Saurabh能够确定你的数据包所采用的路由有其用途。可能一个网络是硬件加密的,另一个是高延迟的,还有一个使用有限,比如3G(*假设是拼写错误),根据不同的场景使用每一个网络是有原因的。如果有代码显示,这会更好。下面是我使用VirtualBox端点而不是NIC的示例。TcpClient client=新的TcpClient();client.client.Bind(新的IPEndPoint(IPAddress.Parse(“192.168.56.1”),32800));client.Connect(“google.com”,80)+1+1似乎我错了,这是有可能的。所以我的答案是错误的,千现在被删除了。这是不正确的。您当然可以使用标准WinSock将TCP/UDP通信限制到特定的网络接口。因此,在Windows上这当然是可能的——正如@Simon Svensson所展示的,您也可以将.NET中的套接字绑定到一个地址。当然,您的数据包可能仍然无法正确路由,但您仍然可以控制其初始源。始终继续重试,是否有任何设置可打开Server@dgvid你能告诉我,如果我的博客条目不再可用,为什么会出现无法访问的网络?我只是在绑定时不断出现“无法连接到远程服务器”异常()返回本地ip地址(192.168…)。