Возникла тут тривиальная задача посмотреть какие IP заняты в локальной сети. И конечно есть целая куча всяких программ сканеров, но хочется же что то свое сварганить )
Немного подумав, пришел к выводу что самое простое это просто пингануть всю локальную сеть. На самом деле Ping это название утилиты которая входит в ОС, а сама эта хрень называется ICMP Echo-Request( запрос ) и ICMP Echo-Reply( ответ ). К стати пинг не гарантирует что устройство не доступно, так как ответ на пинг может быть просто запрещен на устройстве или брандмауэре .
ICMP (Internet Control Message Protocol — протокол межсетевых управляющих сообщений) — сетевой протокол, входящий в стек протоколов TCP/IP.
Вообщем он там зарыт где то глубоко глубоко, писать реализацию своего стека мне уж точно не под силу. По этому будем пользоваться уже готовой системной утилитой. Для отправки ICMP Echo-Request мы должны иметь права АДМИНИСТРАТОРА ( root ). Поехали.
Первым дело узнаем IP нашего сетевого интерфейса, в какой мы вообще сети :
import socket
def getMyIp():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #Создаем сокет (UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Настраиваем сокет на BROADCAST вещание.
s.connect(('<broadcast>', 0))
return s.getsockname()[0]
- socket.AF_INET — для сокета используем IPv4 .
- socket.SOCK_DGRAM — тип сокета. Датаграммный сокет (UDP) .
- getsockname() — Вернет сокету его собственный адрес.
Это наверное не самый элегантный способ.Но должен работать в любой локальной сети, которая позволяет широковещательную рассылку UDP и не требует доступа куда либо. Есть еще идее ? Пишите в комментах )
Далее на надо узнать платформу. В Windows и Linux команда будет выглядеть немного по разному. Для определение ОС в Питоне есть команды platform.system() которая входит в стандартную библиотеку OS . Возвращает имя системы / ОС, например 'Linux'
,'Windows'
, или 'Java'
. Пустая строка возвращается, если значение не может быть определено :
import os
import platform
oc = platform.system()
if (oc == "Windows"):
ping_com = "ping -n 1 "
else:
ping_com = "ping -c 1 "
Введем диапазон адресов для сканирования :
start_point = int(input("Enter the Starting Number: "))
end_point = int(input("Enter the Last Number: "))
Ну теперь напишем саму функцию сканирования :
net = getMyIp()
net_split = net.split('.')
a = '.'
net = net_split[0] + a + net_split[1] + a + net_split[2]+ a
def scan_ip(ip):
addr = net + str(ip)
comm = ping_com + addr
response = os.popen(comm)
data = response.readlines()
for line in data:
if 'TTL' in line:
print(addr, "--> Ping Ok")
break
- os.popen(comm) — Класс Popen Python выполняет дочернюю программу в новом процессе.
- data = response.readlines() — читаем ответ от утилиты.
- Дальше просто парсим ответ, если есть TTL в строке значит пинг успешен.
Еще добавим многопоточность что бы быстрей пинговать. Весь код целиком :
import os
import platform
import threading
import socket
from datetime import datetime
def getMyIp():
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #Создаем сокет (UDP)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) # Настраиваем сокет на BROADCAST вещание.
s.connect(('<broadcast>', 0))
return s.getsockname()[0]
def scan_Ip(ip):
addr = net + str(ip)
comm = ping_com + addr
response = os.popen(comm)
data = response.readlines()
for line in data:
if 'TTL' in line:
print(addr, "--> Ping Ok")
break
net = getMyIp()
print('You IP :',net)
net_split = net.split('.')
a = '.'
net = net_split[0] + a + net_split[1] + a + net_split[2] + a
start_point = int(input("Enter the Starting Number: "))
end_point = int(input("Enter the Last Number: "))
oc = platform.system()
if (oc == "Windows"):
ping_com = "ping -n 1 "
else:
ping_com = "ping -c 1 "
t1 = datetime.now()
print("Scanning in Progress:")
for ip in range(start_point, end_point):
if ip == int(net_split[3]):
continue
potoc = threading.Thread(target=scan_Ip, args=[ip])
potoc.start()
potoc.join()
t2 = datetime.now()
total = t2 - t1
print("Scanning completed in: ", total)

Получилось достаточно простая программка. В следующий раз добавим еще отображение MAC адреса и Vendor . Можно еще добавить определение сетевого имени ПК и т.д.