Imagine a situation, I have PC with two lan cards, one is connected to internet another is connected to local network, how can I detect IP which is connected to internet with C# ?
A hacky way is to fetch and scrape one of the many 'What Is My IP' type websites.
I already search that, i found it in this codeplex project http://www.codeplex.com/xedus. It a none working P2P freeware but there is a class that use the right API to get the lan card witch has the internet ip
The internet connection must be on the same IP network as the default gateway.
There's really foolproof no way to tell from the IP address if you can reach the "internet" or not. Basically you can communicate with your own IP network. Everything else has to go through a gateway. So if you can't see the gateway, you're confined to the local IP network.
The gateway, however, depends on other gateways, so even if you can access the gateway, you may not be able to reach some other network. This can be due to e.g. filtering or lack of routes to the desired networks.
Actually, it makes little sense to talk about the internet in this sense, as you will probably never be able to reach the entire internet at any given moment. Therefore, find out what you need to be able to reach and verify connectivity for that network.
Not 100% accurate (some ISPs don't give you public IP addresses), but you can check if the IP address is on one of the ranges reserved for private addresses. See http://en.wikipedia.org/wiki/Classful_network
For a quick hack (that will certainly become broken with elaborate LAN configurations or IPv6), get a list of all IPs the current machine has, and strip out all IP:s that match any of the following:
10.* 127.* // <- Kudos to Brian for spotting the mistake 172.[16-31].* 192.168.*
Here is an article which could be helpful:
How to Retrieve "Network Interfaces" in C#
The following code is used to retrieve the "network interfaces" in C#. You may recognize the "network interfaces" as "Network and Dial-up Connections": You can access them by using "Start > Setting > Network and Dial-up Connections". C# does not provide a simple way of retrieving this list.
Try this:
static IPAddress getInternetIPAddress()
{
try
{
IPAddress[] addresses = Dns.GetHostAddresses(Dns.GetHostName());
IPAddress gateway = IPAddress.Parse(getInternetGateway());
return findMatch(addresses, gateway);
}
catch (FormatException e) { return null; }
}
static string getInternetGateway()
{
using (Process tracert = new Process())
{
ProcessStartInfo startInfo = tracert.StartInfo;
startInfo.FileName = "tracert.exe";
startInfo.Arguments = "-h 1 208.77.188.166"; // www.example.com
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
tracert.Start();
using (StreamReader reader = tracert.StandardOutput)
{
string line = "";
for (int i = 0; i < 9; ++i)
line = reader.ReadLine();
line = line.Trim();
return line.Substring(line.LastIndexOf(' ') + 1);
}
}
}
static IPAddress findMatch(IPAddress[] addresses, IPAddress gateway)
{
byte[] gatewayBytes = gateway.GetAddressBytes();
foreach (IPAddress ip in addresses)
{
byte[] ipBytes = ip.GetAddressBytes();
if (ipBytes[0] == gatewayBytes[0]
&& ipBytes[1] == gatewayBytes[1]
&& ipBytes[2] == gatewayBytes[2])
{
return ip;
}
}
return null;
}
Note that this implementation of findMatch()
relies on class C matching. If you want to support class B matching, just omit the check for ipBytes[2] == gatewayBytes[2]
.
Edit History:
- Updated to use
www.example.com
. - Updated to include
getInternetIPAddress()
, to show how to use the other methods. - Updated to catch
FormatException
ifgetInternetGateway()
failed to parse the gateway IP. (This can happen if the gateway router is configured such that it doesn't respond to traceroute requests.) - Cited Brian Rasmussen's comment.
- Updated to use the IP for www.example.com, so that it works even when the DNS server is down.
I found a solution:
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
Console.WriteLine(ipProperties.HostName);
foreach (NetworkInterface networkCard in NetworkInterface.GetAllNetworkInterfaces())
{
foreach (GatewayIPAddressInformation gatewayAddr in networkCard.GetIPProperties().GatewayAddresses)
{
Console.WriteLine("Information: ");
Console.WriteLine("Interface type: {0}", networkCard.NetworkInterfaceType.ToString());
Console.WriteLine("Name: {0}", networkCard.Name);
Console.WriteLine("Id: {0}", networkCard.Id);
Console.WriteLine("Description: {0}", networkCard.Description);
Console.WriteLine("Gateway address: {0}", gatewayAddr.Address.ToString());
Console.WriteLine("IP: {0}", System.Net.Dns.GetHostByName(System.Net.Dns.GetHostName()).AddressList[0].ToString());
Console.WriteLine("Speed: {0}", networkCard.Speed);
Console.WriteLine("MAC: {0}", networkCard.GetPhysicalAddress().ToString());
}
}
You could simply read http://myip.dnsomatic.com/
It's a reliable service by OpenDNS, and I use it to get the external IP all the time.
I suggest this simple code since tracert
is not always effective and whatsmyip.com is not specially designed for that purpose :
private void GetIP()
{
WebClient wc = new WebClient();
string strIP = wc.DownloadString("http://checkip.dyndns.org");
strIP = (new Regex(@"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b")).Match(strIP).Value;
wc.Dispose();
return strIP;
}
This is my attempt to get the default IPv4 address without having to resort to DNS or external process calls to commands like ipconfig and route. Hopefully the next version of .Net will provide access to the Windows routing table.
public static IPAddress GetDefaultIPv4Address()
{
var adapters = from adapter in NetworkInterface.GetAllNetworkInterfaces()
where adapter.OperationalStatus == OperationalStatus.Up &&
adapter.Supports(NetworkInterfaceComponent.IPv4)
&& adapter.GetIPProperties().GatewayAddresses.Count > 0 &&
adapter.GetIPProperties().GatewayAddresses[0].Address.ToString() != "0.0.0.0"
select adapter;
if (adapters.Count() > 1)
{
throw new ApplicationException("The default IPv4 address could not be determined as there are two interfaces with gateways.");
}
else
{
UnicastIPAddressInformationCollection localIPs = adapters.First().GetIPProperties().UnicastAddresses;
foreach (UnicastIPAddressInformation localIP in localIPs)
{
if (localIP.Address.AddressFamily == AddressFamily.InterNetwork &&
!localIP.Address.ToString().StartsWith(LINK_LOCAL_BLOCK_PREFIX) &&
!IPAddress.IsLoopback(localIP.Address))
{
return localIP.Address;
}
}
}
return null;
}
Use tracert. The first hop should always be on the same subnet as your internet NIC.
example from command prompt.
tracert google.com
the first line is 10.0.0.254 and my nic has the ip of 10.0.2.48. Then it is a simple exercise of parsing the output from tracert.
An alternative solution (that is probably more accurate) is to use the Windows route
command. Here is some code that works for me on Windows Vista:
static string getInternetConnectionIP()
{
using (Process route = new Process())
{
ProcessStartInfo startInfo = route.StartInfo;
startInfo.FileName = "route.exe";
startInfo.Arguments = "print 0.0.0.0";
startInfo.UseShellExecute = false;
startInfo.RedirectStandardOutput = true;
route.Start();
using (StreamReader reader = route.StandardOutput)
{
string line;
do
{
line = reader.ReadLine();
} while (!line.StartsWith(" 0.0.0.0"));
// the interface is the fourth entry in the line
return line.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries)[3];
}
}
}