I'm totally out of C# hence hanging a little here. I stole the code from https://stackoverflow.com/a/13175574 to read out all adapter settings available on the pc. So far so good.
What I need now is a way to check, which of the adapters are able to connect to an attached device with a given ip address.
I'd like to have a function like "bool CheckIfValidIP(IPAddress adapter, IPAddress IPv4Mask, IPAddress address)".
Can you help me here? I know it's pretty trivial :-/
Edit:
public static class IPAddressExtensions
{
public static IPAddress GetNetworkAddress(this IPAddress address, IPAddress subnetMask)
{
byte[] ipAdressBytes = address.GetAddressBytes();
byte[] subnetMaskBytes = subnetMask.GetAddressBytes();
if (ipAdressBytes.Length != subnetMaskBytes.Length)
throw new ArgumentException("Lengths of IP address and subnet mask do not match.");
byte[] broadcastAddress = new byte[ipAdressBytes.Length];
for (int i = 0; i < broadcastAddress.Length; i++)
{
broadcastAddress[i] = (byte)(ipAdressBytes[i] & (subnetMaskBytes[i]));
}
return new IPAddress(broadcastAddress);
}
public static bool IsInSameSubnet(IPAddress address2, IPAddress address, IPAddress subnetMask)
{
IPAddress network1 = address.GetNetworkAddress(subnetMask);
IPAddress network2 = address2.GetNetworkAddress(subnetMask);
return network1.Equals(network2);
}
}
This code shall do it. Is it safe to use?
A very simple example to get you in the right direction, this is created in .Net core 6:
using System.Net.NetworkInformation;
using System.Net.Sockets;
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
var adaptertList = new List<NetworkInterface>();
const string IpAddressToValidate = "192.168.1.1"; //Both of these values can be retrieved from appsetting.json file
const string IpV4MaskToValidate = "255.255.255.0";
adaptertList = GetValidAdapterList(interfaces);
List<NetworkInterface> GetValidAdapterList(NetworkInterface[] interfaces) {
var adaptertList = new List<NetworkInterface>();
foreach (var adapter in interfaces) {
var ipProps = adapter.GetIPProperties();
foreach (var ip in ipProps.UnicastAddresses) {
if ((adapter.OperationalStatus == OperationalStatus.Up)//Check for any conditions appropriate to your case
&& (ip.Address.AddressFamily == AddressFamily.InterNetwork)) {
if (CheckIsValidIP(ip.Address.ToString(), ip.IPv4Mask.ToString(), IpAddressToValidate, IpV4MaskToValidate)) {
adaptertList.Add(adapter);
continue;//If IP found exit the loop, as the adapter is already added
}
}
}
}
return adaptertList;
}
bool CheckIsValidIP(string ipAddress, string ipV4Mask, string validIpAddress, string validIpV4Mask) {
return (ipAddress == validIpAddress && ipV4Mask == validIpV4Mask);
}
This code will return a list of all the adapter in the machine that meet the Ip address and ipv4mask criteria.
Got this program i am writing in my office in C#.
So i can read all Computer Names From the Domain, fill them into a List and print them out.
Using this Code :
`private void FindComputersInAD()
{
List<string> computerNames = new List<string>();
DirectoryContext dirCtx = new DirectoryContext(DirectoryContextType.Domain, "domain.com");
using (Domain usersDomain = Domain.GetDomain(dirCtx))
using (DirectorySearcher adsearcher = new DirectorySearcher(usersDomain.GetDirectoryEntry()))
{
adsearcher.Filter = ("(objectCategory=computer)");
adsearcher.SizeLimit = 0;
adsearcher.PageSize = 250;
// Let searcher know which properties are going to be used, and only load those
adsearcher.PropertiesToLoad.Add("name");
foreach (SearchResult searchResult in adsearcher.FindAll())
{
if (searchResult.Properties["name"].Count > 0)
{
string computer = (string)searchResult.Properties["name"][0];
computerNames.Add(computer);
}
}
}
computerNames.Sort();
computerNames.ForEach(Console.WriteLine);
}`
Now that i got all the Computer Names, i would like to get their IP Addresses as well.
But there is no such property.
I googled a lot and tried a few things but nothing works.
Can I use the DNS class to do this ?
I use this method to get the Host IP Address :
private void GetLocalIPAddress()
{
string _subString;
var _host = Dns.GetHostEntry(Dns.GetHostName());
foreach (var _ip in _host.AddressList)
{
if (_ip.AddressFamily == AddressFamily.InterNetwork)
{
_subString = _ip.ToString().Substring(_ip.ToString().Length - 2);
//When a IP Address ends with .1, don't add it to the List.
if (_subString != ".1")
{
_hostIPAddress = _ip.ToString();
}
}
}
}
Can I use this also somehow to get the IP Addresses of the Computers ?
I would be very happy if you can help me :)
Thanks in advance
So i found myself an answer.
Since all the computers are in the same domain i openend cmd and tried nslookup.
And it returned the IP Address i wanted.
So i just built a C# DNSLookup Method, looks like this :
private void DNSLookup(string computerNameOrAddress)
{
IPHostEntry hostEntry = Dns.GetHostEntry(computerNameOrAddress);
IPAddress[] ips = hostEntry.AddressList;
foreach (IPAddress ip in ips)
{
Console.WriteLine(" Address: {0}", ip);
}
}
Anyway thanks for looking :)
I need to get the Local IP address of PC but if pc is connected to multiple network the ip is not correct.
I'm using:
public static string GetIPAddress()
{
IPHostEntry host;
string localIP = "?";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
return localIP;
}
Like:
I need get the local ip of adapter with internet or all local ip address.
I can see 2 options:
option 1
loop trough all interfaces using System.Net.NetworkInformation:
static List<IPAddress> GetIpAddress()
{
List<IPAddress> AllIps = new List<IPAddress>();
foreach (NetworkInterface netif in NetworkInterface.GetAllNetworkInterfaces())
{
IPInterfaceProperties properties = netif.GetIPProperties();
foreach (IPAddressInformation unicast in properties.UnicastAddresses)
{
AllIps.Add(unicast.Address);
Console.WriteLine(unicast.Address);
}
}
return AllIps;
}
option 2
find the default gateway to the internet, then match the default gateway address to the interface addresses you found:
public static IPAddress GetDefaultGateway()
{
IPAddress result = null;
var cards = NetworkInterface.GetAllNetworkInterfaces().ToList();
if (cards.Any())
{
foreach (var card in cards)
{
var props = card.GetIPProperties();
if (props == null)
continue;
var gateways = props.GatewayAddresses;
if (!gateways.Any())
continue;
var gateway =
gateways.FirstOrDefault(g => g.Address.AddressFamily.ToString() == "InterNetwork");
if (gateway == null)
continue;
result = gateway.Address;
break;
};
}
return result;
}
now you can combine the 2 options in order to find the interface that is connected to the internet. here is my suggestion to match the default gateway to the correct adapter address. you can also determine the IP address classes
using the IpClass Enumeration that is written in the code i have added:
static void Main(string[] args)
{
// find all interfaces ip adressess
var allAdaptersIp = GetIpAddress();
// find the default gateway
var dg = GetDefaultGateway();
// match the default gateway to the host address => the interface that is connected to the internet => that print host address
Console.WriteLine("ip address that will route you to the world: " + GetInterNetworkHostIp(ref allAdaptersIp, dg, IpClass.ClassC));
Console.ReadLine();
}
enum IpClass
{
ClassA,
ClassB,
ClassC
}
static string GetInterNetworkHostIp(ref List<IPAddress> adapters, IPAddress dg, IpClass ipclassenum)
{
string networkAddress = "";
var result = "" ;
switch (ipclassenum)
{
case IpClass.ClassA:
networkAddress = dg.ToString().Substring(0, dg.ToString().Length - dg.ToString().LastIndexOf(".") );
break;
case IpClass.ClassB:
networkAddress = dg.ToString().Substring(0, dg.ToString().Length - dg.ToString().IndexOf(".",3));
break;
case IpClass.ClassC:
networkAddress = dg.ToString().Substring(0, dg.ToString().Length- dg.ToString().IndexOf(".") );
break;
default:
break;
}
foreach (IPAddress ip in adapters)
{
if (ip.ToString().Contains(networkAddress))
{
result = ip.ToString();
break;
}
}
if (result == "")
result = "no ip was found";
return result;
}
Let's say that I want to send an udp message to every host in my subnet (and then receive an udp message from any host in my subnet):
at the moment I do:
IPAddress broadcast = IPAddress.Parse("192.168.1.255");
but of course I want this to be done dinamically in the event that the subnet is different from 192.168.1/24. I've tried with:
IPAddress broadcast = IPAddress.Broadcast;
but IPAddress.Broadcast represents "255.255.255.255" which can't be used to send messages (it throws an exception)...so:
how do I get the local network adapter broadcast address (or netmask of course)?
THIS IS THE FINAL SOLUTION I CAME UP WITH
public IPAddress getBroadcastIP()
{
IPAddress maskIP = getHostMask();
IPAddress hostIP = getHostIP();
if (maskIP==null || hostIP == null)
return null;
byte[] complementedMaskBytes = new byte[4];
byte[] broadcastIPBytes = new byte[4];
for (int i = 0; i < 4; i++)
{
complementedMaskBytes[i] = (byte) ~ (maskIP.GetAddressBytes().ElementAt(i));
broadcastIPBytes[i] = (byte) ((hostIP.GetAddressBytes().ElementAt(i))|complementedMaskBytes[i]);
}
return new IPAddress(broadcastIPBytes);
}
private IPAddress getHostMask()
{
NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface Interface in Interfaces)
{
IPAddress hostIP = getHostIP();
UnicastIPAddressInformationCollection UnicastIPInfoCol = Interface.GetIPProperties().UnicastAddresses;
foreach (UnicastIPAddressInformation UnicatIPInfo in UnicastIPInfoCol)
{
if (UnicatIPInfo.Address.ToString() == hostIP.ToString())
{
return UnicatIPInfo.IPv4Mask;
}
}
}
return null;
}
private IPAddress getHostIP()
{
foreach (IPAddress ip in (Dns.GetHostEntry(Dns.GetHostName())).AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
return ip;
}
return null;
}
If you get the local IP and subnet, it should be no problem to calculate.
Something like this maybe?
using System;
using System.Net.NetworkInformation;
public class test
{
public static void Main()
{
NetworkInterface[] Interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach(NetworkInterface Interface in Interfaces)
{
if(Interface.NetworkInterfaceType == NetworkInterfaceType.Loopback) continue;
if (Interface.OperationalStatus != OperationalStatus.Up) continue;
Console.WriteLine(Interface.Description);
UnicastIPAddressInformationCollection UnicastIPInfoCol = Interface.GetIPProperties().UnicastAddresses;
foreach(UnicastIPAddressInformation UnicatIPInfo in UnicastIPInfoCol)
{
Console.WriteLine("\tIP Address is {0}", UnicatIPInfo.Address);
Console.WriteLine("\tSubnet Mask is {0}", UnicatIPInfo.IPv4Mask);
}
}
}
}
How to calculate the IP range when the IP address and the netmask is given? Should give you the rest of it.
I need to list IP addresses of all connected hosts in my LAN.
What is the simplest way to do this?
You'll have to do a ping sweep. There's a Ping class in the System.Net namespace. Example follows. Also this is only possible if your computers don't have firewalls running. If they've got a firewall enabled, there's no way to determine this information short of doing SNMP queries on your switches.
System.Net.NetworkInformation.Ping p = new System.Net.NetworkInformation.Ping();
System.Net.NetworkInformation.PingReply rep = p.Send("192.168.1.1");
if (rep.Status == System.Net.NetworkInformation.IPStatus.Success)
{
//host is active
}
The other issue is to determine how large your network is. In most home situations, your network mask will be 24 bits. This means that its set to 255.255.255.0. If your gateway is 192.168.1.1, this means that valid addresses on your network will be 192.168.1.1 to 192.168.1.254. Here's an IP Calculator to help. You'll have to loop through each address and ping the address using the Ping class and check the PingReply.
If you're just looking for the information and aren't concerned with how you get it, you can use NMap. The command would be as follows
nmap -sP 192.168.1.0/24
EDIT:
As far as speed goes, since you're on a local network, you can cut down the timeout interval considerably as your machines shouldn't take more than 100 milliseconds to reply. You can also use SendAsync to ping them all in parallel. The following program will ping 254 address in under half a second.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.NetworkInformation;
using System.Diagnostics;
using System.Net;
using System.Threading;
using System.Net.Sockets;
namespace ConsoleApplication1
{
class Program
{
static CountdownEvent countdown;
static int upCount = 0;
static object lockObj = new object();
const bool resolveNames = true;
static void Main(string[] args)
{
countdown = new CountdownEvent(1);
Stopwatch sw = new Stopwatch();
sw.Start();
string ipBase = "10.22.4.";
for (int i = 1; i < 255; i++)
{
string ip = ipBase + i.ToString();
Ping p = new Ping();
p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
countdown.AddCount();
p.SendAsync(ip, 100, ip);
}
countdown.Signal();
countdown.Wait();
sw.Stop();
TimeSpan span = new TimeSpan(sw.ElapsedTicks);
Console.WriteLine("Took {0} milliseconds. {1} hosts active.", sw.ElapsedMilliseconds, upCount);
Console.ReadLine();
}
static void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
if (resolveNames)
{
string name;
try
{
IPHostEntry hostEntry = Dns.GetHostEntry(ip);
name = hostEntry.HostName;
}
catch (SocketException ex)
{
name = "?";
}
Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
}
else
{
Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
}
lock(lockObj)
{
upCount++;
}
}
else if (e.Reply == null)
{
Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
}
countdown.Signal();
}
}
}
EDIT: After some use of it myself, I modified the program to output a count of how many IPs responded. There's a const bool that if set to true, will cause the program resolve the host names of the IPs. This significantly slows down the scan, though. (under half a second to 16 seconds) Also found that if the IP address is incorrectly specified (made a typo myself), the reply object can be null, so I handled that.
You would need to build an address range (e.g. 192.168.0.1 - 192.168.255.254) and ping each of those addresses. If a response is received, then that host is active.
Asynchronous Ping Tutorial:
http://www.geekpedia.com/tutorial234_Asynchronous-Ping-using-Csharp.html
However, some newer operating systems block ping requests (ICMP). This would need to be disabled in the firewall on each computer for you to receive a response.
You can do it all in managed code. I do it using System.DirectoryServices and System.Net. Basically I get the names of the local computers from DirectoryServices (handling domains and workgroups as I go) then get each host's IP addresses from System.Net.Dns. Here's everything packed into a handy class...
public class NetworkComputer {
private string _domain;
private string _name;
private IPAddress[] _addresses = null;
public string Domain { get { return _domain; } }
public string Name { get { return _name; } }
public IPAddress[] Addresses { get { return _addresses; } }
private NetworkComputer(string domain, string name) {
_domain = domain;
_name = name;
try { _addresses = Dns.GetHostAddresses(name); } catch { }
}
public static NetworkComputer[] GetLocalNetwork() {
var list = new List<NetworkComputer>();
using(var root = new DirectoryEntry("WinNT:")) {
foreach(var _ in root.Children.OfType<DirectoryEntry>()) {
switch(_.SchemaClassName) {
case "Computer":
list.Add(new NetworkComputer("", _.Name));
break;
case "Domain":
list.AddRange(_.Children.OfType<DirectoryEntry>().Where(__ => (__.SchemaClassName == "Computer")).Select(__ => new NetworkComputer(_.Name, __.Name)));
break;
}
}
}
return list.OrderBy(_ => _.Domain).ThenBy(_ => _.Name).ToArray();
}
}
Then just call the static method to get an array of your LAN computers...
var localComputers = NetworkComputer.GetLocalNetwork();
Nazim was correct. And krowe2's reply is factually incorrect. Switches absolutely forward broadcast traffic. You can send a ping to the subnet's broadcast address under the following conditions.
1.a) You are on the same subnet.
1.b) the gateway allows for IP direct broadcast
2.a) The subnet is not part of a fabric network.
2.b) If the subnet is part of a fabric, broadcast traffic is allowed on the subnet.
In about 80% of networks (and about 99.99% of networks using 192.168.1.1 as a gateway) this will work. I'm a network engineer and I do this all the time.
You CAN NOT rely on ICMP (ping) responses to validate the existence of a device on a network. The problem is that no device is required to listen to any traffic. Not ping, not SNMP, not NetBios. The only real way to be sure is to look at the ARP table.
You have to send out any kind of traffic to every IP in the subnet and look at your own ARP table. Because no device can get any traffic until resolve the MAC address of the IP on the local subnet. So before a device decides if it's going to listen to traffic or not, it has to respond to an ARP request. Your device then caches this in it's ARP table and can send frames with the right destination MAC to the other device.
On a Windows PC, the command line command is 'arp -a'. Linux is 'arp -n' if I recall correctly.
You could ping the adress range and note if a host responded. Of course, this will require the host to respond to the ping packets.
namespace WindowsFormsApplication1
{
class WifiInformation
{
static CountdownEvent countdown;
static int upCount = 0;
static object lockObj = new object();
const bool resolveNames = true;
static void Main(string[] args)
{
string ipBase = getIPAddress();
string[] ipParts = ipBase.Split('.');
ipBase = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".";
for (int i = 1; i < 255; i++)
{
string ip = ipBase + i.ToString();
Ping p = new Ping();
p.PingCompleted += new PingCompletedEventHandler(p_PingCompleted);
p.SendAsync(ip, 100, ip);
}
Console.ReadLine();
}
static void p_PingCompleted(object sender, PingCompletedEventArgs e)
{
string ip = (string)e.UserState;
if (e.Reply != null && e.Reply.Status == IPStatus.Success)
{
if (resolveNames)
{
string name;
try
{
IPHostEntry hostEntry = Dns.GetHostEntry(ip);
name = hostEntry.HostName;
}
catch (SocketException ex)
{
name = "?";
}
Console.WriteLine("{0} ({1}) is up: ({2} ms)", ip, name, e.Reply.RoundtripTime);
}
else
{
Console.WriteLine("{0} is up: ({1} ms)", ip, e.Reply.RoundtripTime);
}
lock (lockObj)
{
upCount++;
}
}
else if (e.Reply == null)
{
Console.WriteLine("Pinging {0} failed. (Null Reply object?)", ip);
}
}
public static string getIPAddress()
{
IPHostEntry host;
string localIP = "";
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
{
if (ip.AddressFamily == AddressFamily.InterNetwork)
{
localIP = ip.ToString();
}
}
return localIP;
}
}
}
Instead of arranging a wild ping-party, you could possibly (I really don't know exactly!) use NetBIOS (request the netbios nametable somehow?) http://technet.microsoft.com/en-us/library/cc757216%28WS.10%29.aspx. Or why not ask your DHCP server?
Ping to the global broadcast ip address (192.168.1.255)
Normally we will get the reply from all the host connected to the LAN.. Or if you have any particular network for the lan, ping to that networks broadcast id (i.e the last ip address in that range ).
Then you can know all the ip address connected to the host in lan.