How to get a user's client IP address in ASP.NET? - c#

We have Request.UserHostAddress to get the IP address in ASP.NET, but this is usually the user's ISP's IP address, not exactly the user's machine IP address who for example clicked a link. How can I get the real IP Address?
For example, in a Stack Overflow user profile it is: "Last account activity: 4 hours ago from 86.123.127.8", but my machine IP address is a bit different. How does Stack Overflow get this address?
In some web systems there is an IP address check for some purposes. For example, with a certain IP address, for every 24 hours can the user just have only 5 clicks on download links? This IP address should be unique, not for an ISP that has a huge range of clients or Internet users.
Did I understand well?

Often you will want to know the IP address of someone visiting your website. While ASP.NET has several ways to do this one of the best ways we've seen is by using the "HTTP_X_FORWARDED_FOR" of the ServerVariables collection.
Here's why...
Sometimes your visitors are behind either a proxy server or a router and the standard Request.UserHostAddress only captures the IP address of the proxy server or router. When this is the case the user's IP address is then stored in the server variable ("HTTP_X_FORWARDED_FOR").
So what we want to do is first check "HTTP_X_FORWARDED_FOR" and if that is empty we then simply return ServerVariables("REMOTE_ADDR").
While this method is not foolproof, it can lead to better results. Below is the ASP.NET code in VB.NET, taken from James Crowley's blog post "Gotcha: HTTP_X_FORWARDED_FOR returns multiple IP addresses"
C#
protected string GetIPAddress()
{
System.Web.HttpContext context = System.Web.HttpContext.Current;
string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return context.Request.ServerVariables["REMOTE_ADDR"];
}
VB.NET
Public Shared Function GetIPAddress() As String
Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
Dim sIPAddress As String = context.Request.ServerVariables("HTTP_X_FORWARDED_FOR")
If String.IsNullOrEmpty(sIPAddress) Then
Return context.Request.ServerVariables("REMOTE_ADDR")
Else
Dim ipArray As String() = sIPAddress.Split(New [Char]() {","c})
Return ipArray(0)
End If
End Function

As others have said you can't do what you are asking. If you describe the problem you are trying to solve maybe someone can help?
E.g.
are you trying to uniquely identify your users?
Could you use a cookie, or the session ID perhaps instead of the IP address?
Edit The address you see on the server shouldn't be the ISP's address, as you say that would be a huge range. The address for a home user on broadband will be the address at their router, so every device inside the house will appear on the outside to be the same, but the router uses NAT to ensure that traffic is routed to each device correctly. For users accessing from an office environment the address may well be the same for all users. Sites that use IP address for ID run the risk of getting it very wrong - the examples you give are good ones and they often fail. For example my office is in the UK, the breakout point (where I "appear" to be on the internet) is in another country where our main IT facility is, so from my office my IP address appears to be not in the UK. For this reason I can't access UK only web content, such as the BBC iPlayer). At any given time there would be hundreds, or even thousands, of people at my company who appear to be accessing the web from the same IP address.
When you are writing server code you can never be sure what the IP address you see is referring to. Some users like it this way. Some people deliberately use a proxy or VPN to further confound you.
When you say your machine address is different to the IP address shown on StackOverflow, how are you finding out your machine address? If you are just looking locally using ipconfig or something like that I would expect it to be different for the reasons I outlined above. If you want to double check what the outside world thinks have a look at whatismyipaddress.com/.
This Wikipedia link on NAT will provide you some background on this.

UPDATE:
Thanks to Bruno Lopes. If several ip addresses could come then need to use this method:
private string GetUserIP()
{
string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipList))
{
return ipList.Split(',')[0];
}
return Request.ServerVariables["REMOTE_ADDR"];
}

If is c# see this way, is very simple
string clientIp = (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ??
Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();

What else do you consider the user IP address? If you want the IP address of the network adapter, I'm afraid there's no possible way to do it in a Web app. If your user is behind NAT or other stuff, you can't get the IP either.
Update: While there are Web sites that use IP to limit the user (like rapidshare), they don't work correctly in NAT environments.

I think I should share my experience with you all. Well I see in some situations REMOTE_ADDR will NOT get you what you are looking for. For instance, if you have a Load Balancer behind the scene and if you are trying to get the Client's IP then you will be in trouble. I checked it with my IP masking software plus I also checked with my colleagues being in different continents. So here is my solution.
When I want to know the IP of a client, I try to pick every possible evidence so I could determine if they are unique:
Here I found another sever-var that could help you all if you want to get exact IP of the client side. so I am using : HTTP_X_CLUSTER_CLIENT_IP
HTTP_X_CLUSTER_CLIENT_IP always gets you the exact IP of the client. In any case if its not giving you the value, you should then look for HTTP_X_FORWARDED_FOR as it is the second best candidate to get you the client IP and then the REMOTE_ADDR var which may or may not return you the IP but to me having all these three is what I find the best thing to monitor them.
I hope this helps some guys.

You can use:
System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();

All of the responses so far take into account the non-standardized, but very common, X-Forwarded-For header. There is a standardized Forwarded header which is a little more difficult to parse out. Some examples are as follows:
Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17
I have written a class that takes both of these headers into account when determining a client's IP address.
using System;
using System.Web;
namespace Util
{
public static class IP
{
public static string GetIPAddress()
{
return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
}
internal static string GetIPAddress(HttpRequestBase request)
{
// handle standardized 'Forwarded' header
string forwarded = request.Headers["Forwarded"];
if (!String.IsNullOrEmpty(forwarded))
{
foreach (string segment in forwarded.Split(',')[0].Split(';'))
{
string[] pair = segment.Trim().Split('=');
if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
{
string ip = pair[1].Trim('"');
// IPv6 addresses are always enclosed in square brackets
int left = ip.IndexOf('['), right = ip.IndexOf(']');
if (left == 0 && right > 0)
{
return ip.Substring(1, right - 1);
}
// strip port of IPv4 addresses
int colon = ip.IndexOf(':');
if (colon != -1)
{
return ip.Substring(0, colon);
}
// this will return IPv4, "unknown", and obfuscated addresses
return ip;
}
}
}
// handle non-standardized 'X-Forwarded-For' header
string xForwardedFor = request.Headers["X-Forwarded-For"];
if (!String.IsNullOrEmpty(xForwardedFor))
{
return xForwardedFor.Split(',')[0];
}
return request.UserHostAddress;
}
}
}
Below are some unit tests that I used to validate my solution:
using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UtilTests
{
[TestClass]
public class IPTests
{
[TestMethod]
public void TestForwardedObfuscated()
{
var request = new HttpRequestMock("for=\"_gazonk\"");
Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv6()
{
var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv4()
{
var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv4WithPort()
{
var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedMultiple()
{
var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
}
}
public class HttpRequestMock : HttpRequestBase
{
private NameValueCollection headers = new NameValueCollection();
public HttpRequestMock(string forwarded)
{
headers["Forwarded"] = forwarded;
}
public override NameValueCollection Headers
{
get { return this.headers; }
}
}
}

IP addresses are part of the Network layer in the "seven-layer stack". The Network layer can do whatever it wants to do with the IP address. That's what happens with a proxy server, NAT, relay, or whatever.
The Application layer should not depend on the IP address in any way. In particular, an IP Address is not meant to be an identifier of anything other than the idenfitier of one end of a network connection. As soon as a connection is closed, you should expect the IP address (of the same user) to change.

If you are using CloudFlare,
you can try this Extension Method:
public static class IPhelper
{
public static string GetIPAddress(this HttpRequest Request)
{
if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();
if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();
return Request.UserHostAddress;
}
}
then
string IPAddress = Request.GetIPAddress();

string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;

What you can do is store the router IP of your user and also the forwarded IP and try to make it reliable using both the IPs [External Public and Internal Private]. But again after some days client may be assigned new internal IP from router but it will be more reliable.

Combining the answers from #Tony and #mangokun, I have created the following extension method:
public static class RequestExtensions
{
public static string GetIPAddress(this HttpRequest Request)
{
if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();
if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
{
string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
}
return Request.UserHostAddress;
}
}

public static class Utility
{
public static string GetClientIP(this System.Web.UI.Page page)
{
string _ipList = page.Request.Headers["CF-CONNECTING-IP"].ToString();
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
_ipList = page.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"];
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
_ipList = page.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrWhiteSpace(_ipList))
{
return _ipList.Split(',')[0].Trim();
}
else
{
return page.Request.ServerVariables["REMOTE_ADDR"].ToString().Trim();
}
}
}
}
}
Use;
string _ip = this.GetClientIP();

use in ashx file
public string getIP(HttpContext c)
{
string ips = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ips))
{
return ips.Split(',')[0];
}
return c.Request.ServerVariables["REMOTE_ADDR"];
}

In NuGet package install Microsoft.AspNetCore.HttpOverrides
Then try:
public class ClientDeviceInfo
{
private readonly IHttpContextAccessor httpAccessor;
public ClientDeviceInfo(IHttpContextAccessor httpAccessor)
{
this.httpAccessor = httpAccessor;
}
public string GetClientLocalIpAddress()
{
return httpAccessor.HttpContext.Connection.LocalIpAddress.ToString();
}
public string GetClientRemoteIpAddress()
{
return httpAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
}
public string GetClientLocalPort()
{
return httpAccessor.HttpContext.Connection.LocalPort.ToString();
}
public string GetClientRemotePort()
{
return httpAccessor.HttpContext.Connection.RemotePort.ToString();
}
}

Its easy.Try it:
var remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
just it :))

use this
Dns.GetHostEntry(Dns.GetHostName())

Hello guys Most of the codes you will find will return you server ip address not client ip address .however this code returns correct client ip address.Give it a try.
For More info just check this
https://www.youtube.com/watch?v=Nkf37DsxYjI
for getting your local ip address using javascript you can use
put this code inside your script tag
<script>
var RTCPeerConnection = /*window.RTCPeerConnection ||*/
window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
if (RTCPeerConnection) (function () {
var rtc = new RTCPeerConnection({ iceServers: [] });
if (1 || window.mozRTCPeerConnection) {
rtc.createDataChannel('', { reliable: false });
};
rtc.onicecandidate = function (evt) {
if (evt.candidate)
grepSDP("a=" + evt.candidate.candidate);
};
rtc.createOffer(function (offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function (e) { console.warn("offer failed", e); });
var addrs = Object.create(null);
addrs["0.0.0.0"] = false;
function updateDisplay(newAddr) {
if (newAddr in addrs) return;
else addrs[newAddr] = true;
var displayAddrs = Object.keys(addrs).filter(function
(k) { return addrs[k]; });
document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
}
function grepSDP(sdp) {
var hosts = [];
sdp.split('\r\n').forEach(function (line) {
if (~line.indexOf("a=candidate")) {
var parts = line.split(' '),
addr = parts[4],
type = parts[7];
if (type === 'host') updateDisplay(addr);
} else if (~line.indexOf("c=")) {
var parts = line.split(' '),
addr = parts[2];
updateDisplay(addr);
}
});
}
})(); else
{
document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";
}
</script>
<body>
<div id="list"></div>
</body>
and For getting your public ip address you can use
put this code inside your script tag
function getIP(json) {
document.write("My public IP address is: ", json.ip);
}
<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>

Simply
var ip = Request.UserHostAddress;
That's all...

Try:
using System.Net;
public static string GetIpAddress() // Get IP Address
{
string ip = "";
IPHostEntry ipEntry = Dns.GetHostEntry(GetCompCode());
IPAddress[] addr = ipEntry.AddressList;
ip = addr[2].ToString();
return ip;
}
public static string GetCompCode() // Get Computer Name
{
string strHostName = "";
strHostName = Dns.GetHostName();
return strHostName;
}

Related

Get IP address from hostname in LAN

I found many samples on how to get a hostname by an IP address, how can I get the IP address of a host in the LAN?
Try this
public static void DoGetHostAddresses(string hostname)
{
IPAddress[] ips;
ips = Dns.GetHostAddresses(hostname);
Console.WriteLine("GetHostAddresses({0}) returns:", hostname);
foreach (IPAddress ip in ips)
{
Console.WriteLine(" {0}", ip);
}
}
i got this from http://msdn.microsoft.com/en-us/library/system.net.dns.gethostaddresses.aspx
Here is simple code if you want to get the IP Address(V4) from your pc.
Import this library into your class
using System.Net;
Initialize and declare these variables into your codes. They contain hostname, ipaddress and an array of Host Addresses:
string HostName = Dns.GetHostName().ToString();
IPAddress[] IpInHostAddress = Dns.GetHostAddresses(HostName);
string IPV4Address = IpInHostAddress[1].ToString(); //Default IPV4Address. This might be the ip address you need to retrieve
string IPV6Address = IpInHostAddress[0].ToString(); //Default Link local IPv6 Address
Open your command prompt, just type "ipconfig" and press enter.Once you are done, you could check if the string IPV4Address matches to IPv4Address in our pc.
As long as you know the name of a machine, you can use Dns.GetHostAddresses. Your network DNS should recognize it as LAN computer and return proper IP.
Use Dns.GetHostEntry(hostname) instead of obsolete Dns.GetHostAddresses.
Here is an excellent example of how it is doing: http://www.codeproject.com/Articles/854/How-To-Get-IP-Address-Of-A-Machine
you could use the windows management classes to do this, it also works for remote machines that are in the same domain (but I don't know if they need to enable or disable any security or policy settings for this to work). for example:
public List<NetworkAdapter> GetAdapterList()
{
ManagementClass mgmt = new ManagementClass("Win32_NetworkAdapterConfiguration ");
ManagementObjectCollection moc = mgmt.GetInstances();
List<NetworkAdapter> adapters = new List<NetworkAdapter>();
// Search for adapters with IP addresses
foreach(ManagementObject mob in moc)
{
string[] addresses = (string[])mob.Properties["IPAddress"].Value;
if (null == addresses)
{
continue;
}
NetworkAdapter na = new NetworkAdapter();
na.Description = (string) mob.Properties["Description"].Value;
na.MacAddress = (string) mob.Properties["MACAddress"].Value;
na.IPAddresses = addresses;
adapters.Add(na);
}
return adapters;
}
and to access a remote machine create the management class like this instead:
ManagementClass mgmt = new ManagementClass
(\\\\servername\\root\\cimv2:Win32_NetworkAdapterConfiguration);
this approach may get you more IPs than just the ones that have been registered in the DNS.

Get closest Domain Controller in current AD site without hard coding information

For instances when Active Directory takes too long to replicate data between sites, I need to ensure that the local AD replica contains the most up to date information.
How can I get a list of DomainControllers for the current site?
I haven't found anything on Codeproject or on StackOverflow
Going to all this trouble is probably wasted effort. Unless you are experiencing issues with the built in logic for finding a domain controller you should just go with the built in method that returns one. According to Microsoft it automatically tries to find the closes one: http://technet.microsoft.com/en-us/library/cc978016.aspx.
Just use the static DomainController.FindOne method and pass in your directorycontext.
Update
Alright, try the code below, let me know how it works for you. It pings each, returns the roundtrip time, if -1 (no connection) it skips it. Flags PDC status if present. Orders by PDC status, followed by ping round trip.
static void Main(string[] args)
{
var dcsInOrder = (from DomainController c in Domain.GetCurrentDomain().DomainControllers
let responseTime = Pinger(c.Name)
where responseTime >=0
let pdcStatus = c.Roles.Contains(ActiveDirectoryRole.PdcRole)
orderby pdcStatus, responseTime
select new {DC = c, ResponseTime = responseTime}
).ToList();
foreach (var dc in dcsInOrder)
{
System.Console.WriteLine(dc.DC.Name + " - " + dc.ResponseTime);
}
System.Console.ReadLine();
}
private static int Pinger(string address)
{
Ping p = new Ping();
try
{
PingReply reply = p.Send(address, 3000);
if (reply.Status == IPStatus.Success) return (int)reply.RoundtripTime;
}
catch { }
return -1;
}
First, I'll answer the question that you actually asked:
System.DirectoryServices.ActiveDirectory.ActiveDirectorySite.GetComputerSite().Servers
But it seems like you're asking how to make sure that you're talking to the closest domain controller possible. Windows doesn't exactly provide this functionality, the best it will do is give you a domain controller in the same site that the code is running from.
I think the first thing to check is that you have your sites and subnets configured correctly. Run Active Directory Sites and Services, and make sure that subnets and domain controllers are assigned to the correct sites.
This MSDN page (and the Technet article in Peter's answer) says that you must be searching by the DNS name for the DC Locator to attempt to find a DC in the current site. I don't know if the Name property of the Domain class is the DNS domain name.
I have to assume that DomainController.FindOne is a wrapper for DsGetDcName. At that link, you can find how to turn on tracing for that function. You can use this if you still have problems, or maybe you should just PInvoke this function.
Here is a code sample that has no hard coding of DCs. Comments and criticism are welcome.
/// <summary>
/// For best results ensure all hosts are pingable, and turned on.
/// </summary>
/// <returns>An ordered list of DCs with the PDCE first</returns>
static LinkedList<DomainController> GetNearbyDCs()
{
LinkedList<DomainController> preferredDCs = new LinkedList<DomainController>();
List<string> TestedDCs = new List<string>();
using (var mysite = ActiveDirectorySite.GetComputerSite())
{
using (var currentDomain = Domain.GetCurrentDomain())
{
DirectoryContext dctx = new DirectoryContext(DirectoryContextType.Domain, currentDomain.Name);
var listOfDCs = DomainController.FindAll(dctx, mysite.Name);
foreach (DomainController item in listOfDCs)
{
Console.WriteLine(item.Name );
if (IsConnected(item.IPAddress))
{
// Enumerating "Roles" will cause the object to bind to the server
ActiveDirectoryRoleCollection rollColl = item.Roles;
if (rollColl.Count > 0)
{
foreach (ActiveDirectoryRole roleItem in rollColl)
{
if (!TestedDCs.Contains(item.Name))
{
TestedDCs.Add(item.Name);
if (roleItem == ActiveDirectoryRole.PdcRole)
{
preferredDCs.AddFirst(item);
break;
}
else
{
if (preferredDCs.Count > 0)
{
var tmp = preferredDCs.First;
preferredDCs.AddBefore(tmp, item);
}
else
{
preferredDCs.AddFirst(item);
}
break;
}
}
}
}
else
{
// The DC exists but has no roles
TestedDCs.Add(item.Name);
if (preferredDCs.Count > 0)
{
var tmp = preferredDCs.First;
preferredDCs.AddBefore(tmp, item);
}
else
{
preferredDCs.AddFirst(item);
}
}
}
else
{
preferredDCs.AddLast(item);
}
}
}
}
return preferredDCs;
}
static bool IsConnected(string hostToPing)
{
string pingurl = string.Format("{0}", hostToPing);
string host = pingurl;
bool result = false;
Ping p = new Ping();
try
{
PingReply reply = p.Send(host, 3000);
if (reply.Status == IPStatus.Success)
return true;
}
catch { }
return result;
}
Here's my approach using powershell but I'm sure it's a simple implementation in c#, etc. If DHCP is setup correctly, the Primary DNS server in your subnet should be the closest Domain Controller. So the following code should grab the first DNS IP and resolve it to the hostname of the closest DC. This doesn't require RSAT or credentials and contains no specific properties of the current domain.
$NetItems = #(Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter "IPEnabled = 'True'" -ComputerName $env:COMPUTERNAME)
foreach ($objItem in $NetItems)
{
if ($objItem.{DNSServerSearchOrder}.Count -ge 1)
{
$PrimaryDNS = $objItem.DNSServerSearchOrder[0]
$domain = $objItem.DNSDomain
break
}
}
[System.Net.Dns]::GetHostbyAddress($PrimaryDNS).hostname -replace ".$($domain)",""

Checking that a user has correctly entered an IP Address

I am currently working on a C# project where I need to validate the text that a user has entered into a text box.
One of the validations required is that it checks to ensure that an IP address has been entered correctly.
How would I go about doing this validation of the IP address.
Thanks for any help you can provide.
You can use IPAddress.Parse Method .NET Framework 1.1. Or, if you are using .NET 4.0, see documentation for IPAddress.TryParse Method .NET Framework 4.
This method determines if the contents of a string represent a valid IP address. In .NET 1.1, the return value is the IP address. In .NET 4.0, the return value indicates success/failure, and the IP address is returned in the IPAddress passed as an out parameter in the method call.
edit: alright I'll play the game for bounty :) Here's a sample implementation as an extension method, requiring C# 3+ and .NET 4.0:
using System;
using System.Net;
using System.Text.RegularExpressions;
namespace IPValidator
{
class Program
{
static void Main (string[] args)
{
Action<string> TestIP = (ip) => Console.Out.WriteLine (ip + " is valid? " + ip.IsValidIP ());
TestIP ("99");
TestIP ("99.99.99.99");
TestIP ("255.255.255.256");
TestIP ("abc");
TestIP ("192.168.1.1");
}
}
internal static class IpExtensions
{
public static bool IsValidIP (this string address)
{
if (!Regex.IsMatch (address, #"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"))
return false;
IPAddress dummy;
return IPAddress.TryParse (address, out dummy);
}
}
}
It seems that you are only concerned with validating IPv4 IP Address strings in X.X.X.X format. If so, this code is straight forward for that task:
string ip = "127.0.0.1";
string[] parts = ip.Split('.');
if (parts.Length < 4)
{
// not a IPv4 string in X.X.X.X format
}
else
{
foreach(string part in parts)
{
byte checkPart = 0;
if (!byte.TryParse(part, out checkPart))
{
// not a valid IPv4 string in X.X.X.X format
}
}
// it is a valid IPv4 string in X.X.X.X format
}
If you want to see if the IP address actually exists, you can use the Ping class.
insta's answer was closer before he added the incorrect regexp.
public static bool IsValidIP(string ipAddress)
{
IPAddress unused;
return IPAddress.TryParse(ipAddress, out unused);
}
Or since the OP doesn't want to include integer IPv4 addresses that aren't full dotted quads:
public static bool IsValidIP(string ipAddress)
{
IPAddress unused;
return IPAddress.TryParse(ipAddress, out unused)
&&
(
unused.AddressFamily != AddressFamily.InterNetwork
||
ipAddress.Count(c => c == '.') == 3
);
}
Testing:
IsValidIP("fe80::202:b3ff:fe1e:8329") returns true (correct).
IsValidIP("127.0.0.1") returns true (correct).
IsValidIP("What's an IP address?") returns false (correct).
IsValidIP("127") returns true with first version, false with second (correct).
IsValidIP("127.0") returns true with first version, false with second (correct).
I'd use a regex.
^((25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)\.){3}(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)$
Using named groups, it could be clearer. It is written in Ruby. I don't know C# but I guess that the regex support is complete in that language and that named groups might exist.
/(?<number>(25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){0}^(\g<number>\.){3}\g<number>$/
Here's my solution:
using System.Net.NetworkInformation;
using System.Net;
/// <summary>
/// Return true if the IP address is valid.
/// </summary>
/// <param name="address"></param>
/// <returns></returns>
public bool TestIpAddress (string address)
{
PingReply reply;
Ping pingSender = new Ping ();
try
{
reply = pingSender.Send (address);
}
catch (Exception)
{
return false;
}
return reply.Status == IPStatus.Success;
}

IPAddress.Parse() using port on IPv4

I'm trying to parse a string containing an IP address and a port using IPAddress.Parse. This works well with IPv6 addresses but not with IPv4 addresses. Can somone explain why this happens?
The code I'm using is:
IPAddress.Parse("[::1]:5"); //Valid
IPAddress.Parse("127.0.0.1:5"); //null
Uri url;
IPAddress ip;
if (Uri.TryCreate(String.Format("http://{0}", "127.0.0.1:5"), UriKind.Absolute, out url) &&
IPAddress.TryParse(url.Host, out ip))
{
IPEndPoint endPoint = new IPEndPoint(ip, url.Port);
}
This happens because the port is not part of the IP address. It belongs to TCP/UDP, and you'll have to strip it out first. The Uri class might be helpful for this.
IPAddress is not IP+Port. You want IPEndPoint.
Example from http://www.java2s.com/Code/CSharp/Network/ParseHostString.htm
public static void ParseHostString(string hostString, ref string hostName, ref int port)
{
hostName = hostString;
if (hostString.Contains(":"))
{
string[] hostParts = hostString.Split(':');
if (hostParts.Length == 2)
{
hostName = hostParts[0];
int.TryParse(hostParts[1], out port);
}
}
}
Edit: Ok, I'll admit that wasn't the most elegant solution. Try this one I wrote (just for you) instead:
// You need to include some usings:
using System.Text.RegularExpressions;
using System.Net;
// Then this code (static is not required):
private static Regex hostPortMatch = new Regex(#"^(?<ip>(?:\[[\da-fA-F:]+\])|(?:\d{1,3}\.){3}\d{1,3})(?::(?<port>\d+))?$", System.Text.RegularExpressions.RegexOptions.Compiled);
public static IPEndPoint ParseHostPort(string hostPort)
{
Match match = hostPortMatch.Match(hostPort);
if (!match.Success)
return null;
return new IPEndPoint(IPAddress.Parse(match.Groups["ip"].Value), int.Parse(match.Groups["port"].Value));
}
Note that this one ONLY accepts IP address, not hostname. If you want to support hostname you'll either have to resolve it to IP or not use IPAddress/IPEndPoint.
IPAddress.Parse is meant to take A string that contains an IP address in dotted-quad notation for IPv4 and in colon-hexadecimal notation for IPv6. So your first example works for IPv6 and your second example fails because it doesnt support a port for IPv4. Link http://msdn.microsoft.com/en-us/library/system.net.ipaddress.parse.aspx
As Tedd Hansen pointed out, what you are trying to parse is not an IP address but an IP endpoint (IP address + port). And since .NET Core 3.0, you can use IPEndPoint.TryParse to parse a string as an IPEndPoint:
if (IPEndPoint.TryParse("127.0.0.1:5", out IPEndPoint endpoint))
{
// parsed successfully, you can use the "endpoint" variable
Console.WriteLine(endpoint.Address.ToString()); // writes "127.0.0.1"
Console.WriteLine(endpoint.Port.ToString()); // writes "5"
}
else
{
// failed to parse
}
If you work on older versions of .net you can take IPEndPoint.Parse implementation from open source: https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Primitives/src/System/Net/IPEndPoint.cs
To add my two cents... Since Microsoft itself implemented TryParse in NET Core 3.0 I've opted to stop using my custom IP+Port parser and kindly borrowed their code with some adaptations:
public static class IPEndPointParserExtension
{
public static bool TryParseAsIPEndPoint(this string s, out IPEndPoint result) {
#if NETCOREAPP3_0_OR_GREATER
return IPEndPoint.TryParse(s, out result);
#else
int addressLength = s.Length; // If there's no port then send the entire string to the address parser
int lastColonPos = s.LastIndexOf(':');
// Look to see if this is an IPv6 address with a port.
if (lastColonPos > 0) {
if (s[lastColonPos - 1] == ']')
addressLength = lastColonPos;
// Look to see if this is IPv4 with a port (IPv6 will have another colon)
else if (s.Substring(0, lastColonPos).LastIndexOf(':') == -1)
addressLength = lastColonPos;
}
if (IPAddress.TryParse(s.Substring(0, addressLength), out IPAddress address)) {
long port = 0;
if (addressLength == s.Length ||
(long.TryParse(s.Substring(addressLength + 1), out port)
&& port <= IPEndPoint.MaxPort)) {
result = new IPEndPoint(address, (int)port);
return true;
}
}
result = null;
return false;
#endif
}
public static IPEndPoint AsIPEndPoint(this string s) =>
s.TryParseAsIPEndPoint(out var endpoint)
? endpoint
: throw new FormatException($"'{s}' is not a valid IP Endpoint");
}
My changes were to basically exchange Span<char> for string and make it an extension method of the class String itself. I've also conditionally compile to use Microsoft's implementation if it is available (NET Core 3.0 or greater).
The following nUnit tests show how to use the code:
[Test]
public void CanParseIpv4WithPort() {
var sIp = "192.168.0.233:8080";
if (sIp.TryParseAsIPEndPoint(out var endpoint)) {
var expected = new IPEndPoint(new IPAddress(new byte[] { 192, 168, 0, 233 }), 8080);
Assert.AreEqual(expected, endpoint);
} else
Assert.Fail($"Failed to parse {sIp}");
}
[Test]
public void CanParseIpv6WithPort() {
var sIp = "[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443";
if (sIp.TryParseAsIPEndPoint(out var endpoint)) {
var expected = new IPEndPoint(IPAddress.Parse("2001:db8:85a3:8d3:1319:8a2e:370:7348"), 443);
Assert.AreEqual(expected, endpoint);
} else
Assert.Fail($"Failed to parse {sIp}");
}
You can also use AsIpEndPoint which will throw an exception if it fails to parse the IP address and port (port is optional):
var ep = "127.0.0.1:9000".AsIPEndPoint();

Get IP of my machine C# with virtual machine installed

I want to get the current IP address of the computer that has say 3 virtual machines (VM Ware) installed. I want to get LAN address of that computer.
current code that i have returns me an array but how to identify current computer lan address ?
public static string getThisCompIPAddress()
{
IPAddress[] addresslist = Dns.GetHostAddresses(Dns.GetHostName());
return (addresslist[0].ToString());
}
addresslist returns an array of 3 IP addresses
You could try the NetworkInterface class, and try to match the name or physical address of the LAN connection to find out the real one. Maybe searching within this class and it's members you can find something that suits your needs.
Here is a simple method to provide some usage info:
using System.Net.NetworkInformation;
...
static void ViewNetworkInfo()
{
NetworkInterface[] networks = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface nw in networks)
{
Console.WriteLine(nw.Name);
Console.WriteLine(nw.GetPhysicalAddress().ToString());
IPInterfaceProperties ipProps = nw.GetIPProperties();
foreach (UnicastIPAddressInformation ucip in ipProps.UnicastAddresses)
{
Console.WriteLine(ucip.Address.ToString());
}
Console.WriteLine();
}
Console.ReadKey();
}
I've tried all of the solutions above but couldn't get the ip from my "real" machine and not the virtual one. I've managed to use this to get the IP from my virtual machine:
IPAddress[] addresslist = Dns.GetHostAddresses(Environment.ExpandEnvironmentVariables("%CLIENTNAME%"));
The reason why I used it this way is that the function Dns.GetHostAddresses return the adresses of the given host, so if you use the Dns.GetHostName() function it will return the virtual-machine name and not the local machine, but using the name of the machine where you can find using the: Environment.ExpandEnvironmentVariables("%CLIENTNAME%") you can get the client name and not the virtual-machine name, this way you can get the real IP of your local machine.
I hope this helps.
public static ArrayList getThisCompIPAddress()
{
ArrayList strArrIpAdrs = new ArrayList();
ArrayList srtIPAdrsToReturn = new ArrayList();
addresslist = Dns.GetHostAddresses(Dns.GetHostName());
for (int i = 0; i < addresslist.Length; i++)
{
try
{
long ip = addresslist[i].Address;
strArrIpAdrs.Add(addresslist[i]);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
foreach (IPAddress ipad in strArrIpAdrs)
{
lastIndexOfDot = ipad.ToString().LastIndexOf('.');
substring = ipad.ToString().Substring(0, ++lastIndexOfDot);
if (!(srtIPAdrsToReturn.Contains(substring)) && !(substring.Equals("")))
{
srtIPAdrsToReturn.Add(substring);
}
}
return srtIPAdrsToReturn;
}
this is 100% working, the real problem was that it was throwing error while calculating Address that returns long. Error Code is 10045

Categories

Resources