Пинг или иным образом узнать, находится ли устройство в сети по MAC-адресу в C#.
-
24-09-2019 - |
Вопрос
Я разрабатываю приложение для домашней безопасности.Единственное, что я хотел бы сделать, это автоматически выключать и включать его в зависимости от того, нахожусь ли я дома или нет.У меня есть телефон с Wi-Fi, который автоматически подключается к моей сети, когда я дома.
Телефон подключается и получает свой адрес через DHCP.Хотя я мог бы настроить его на использование статического IP-адреса, я бы предпочел этого не делать.Есть ли какой-либо тип «Ping» или его эквивалент в C#/.Net, который может взять MAC-адрес устройства и сообщить мне, активно ли оно в данный момент в сети?
Редактировать: Чтобы уточнить: я запускаю на ПК программное обеспечение, которое, как мне хотелось бы, могло обнаружить телефон в той же локальной сети.
Редактировать: Вот код, который я придумал благодаря помощи Спулсона.Он надежно определяет, есть ли в доме какой-либо из интересующих меня телефонов.
private bool PhonesInHouse()
{
Ping p = new Ping();
// My home network is 10.0.23.x, and the DHCP
// pool runs from 10.0.23.2 through 10.0.23.127.
int baseaddr = 10;
baseaddr <<= 8;
baseaddr += 0;
baseaddr <<= 8;
baseaddr += 23;
baseaddr <<= 8;
// baseaddr is now the equivalent of 10.0.23.0 as an int.
for(int i = 2; i<128; i++) {
// ping every address in the DHCP pool, in a separate thread so
// that we can do them all at once
IPAddress ip = new IPAddress(IPAddress.HostToNetworkOrder(baseaddr + i));
Thread t = new Thread(() =>
{ try { Ping p = new Ping(); p.Send(ip, 1000); } catch { } });
t.Start();
}
// Give all of the ping threads time to exit
Thread.Sleep(1000);
// We're going to parse the output of arp.exe to find out
// if any of the MACs we're interested in are online
ProcessStartInfo psi = new ProcessStartInfo();
psi.Arguments = "-a";
psi.FileName = "arp.exe";
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = true;
bool foundone = false;
using (Process pro = Process.Start(psi))
{
using (StreamReader sr = pro.StandardOutput)
{
string s = sr.ReadLine();
while (s != null)
{
if (s.Contains("Interface") ||
s.Trim() == "" ||
s.Contains("Address"))
{
s = sr.ReadLine();
continue;
}
string[] parts = s.Split(new char[] { ' ' },
StringSplitOptions.RemoveEmptyEntries);
// config.Phones is an array of strings, each with a MAC
// address in it.
// It's up to you to format them in the same format as
// arp.exe
foreach (string mac in config.Phones)
{
if (mac.ToLower().Trim() == parts[1].Trim().ToLower())
{
try
{
Ping ping = new Ping();
PingReply pingrep = ping.Send(parts[0].Trim());
if (pingrep.Status == IPStatus.Success)
{
foundone = true;
}
}
catch { }
break;
}
}
s = sr.ReadLine();
}
}
}
return foundone;
}
Решение
Другой подход заключается в использовании ping
и arp
инструменты.Поскольку пакеты ARP могут оставаться только в одном и том же широковещательном домене, вы можете проверить широковещательный адрес вашей сети, и каждый клиент ответит ответом ARP.Каждый из этих ответов кэшируется в вашей таблице ARP, которую вы можете просмотреть с помощью команды arp -a
.Итак, краткое изложение:
rem Clear ARP cache
netsh interface ip delete arpcache
rem Ping broadcast addr for network 192.168.1.0
ping -n 1 192.168.1.255
rem View ARP cache to see if the MAC addr is listed
arp -a
Некоторые из них можно выполнить в управляемом коде, например в System.Net.NetworkInformation
пространство имен.
Примечание:Очистка кэша ARP может незначительно повлиять на производительность сети за счет очистки кэшированных записей других локальных серверов.Однако в любом случае кеш обычно очищается каждые 20 минут или меньше.
Другие советы
Вы можете использовать Протокол RARP для широковещательной передачи запроса о том, кому принадлежит этот MAC-адрес.Владелец ответит своим IP-адресом.Я не знаю инструмента или библиотеки RARP, которые можно было бы порекомендовать, поэтому вы можете рассмотреть возможность написания собственного сетевого уровня для отправки/получения этих пакетов.