我的电脑有几种不同的互联网连接。 LAN,WLAN,WiFi或3G。所有这些都是活动的,机器可以使用它们中的任何一个。
现在我想告诉我的应用程序使用其中一个可用的连接。例如,我想告诉我的应用程序只使用WiFi,而其他软件可能会使用其他东西。
在我的c#应用程序中,我使用HttpWebRequest
和HttpWebResponse
等类。
这甚至可能吗?
答案 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上做到这一点。