简体   繁体   English

Python中本地网络的IP地址/主机名列表

[英]List of IP addresses/hostnames from local network in Python

How can I get a list of the IP addresses or host names from a local network easily in Python?如何在 Python 中轻松地从本地网络获取 IP 地址或主机名列表?

It would be best if it was multi-platform, but it needs to work on Mac OS X first, then others follow.最好是多平台的,但它需要先在 Mac OS X 上运行,然后其他的。

Edit: By local I mean all active addresses within a local network, such as 192.168.xxx.xxx .编辑:本地是指本地网络中的所有活动地址,例如192.168.xxx.xxx

So, if the IP address of my computer (within the local network) is 192.168.1.1 , and I have three other connected computers, I would want it to return the IP addresses 192.168.1.2 , 192.168.1.3 , 192.168.1.4 , and possibly their hostnames.因此,如果我的计算机(在本地网络内)的 IP 地址是192.168.1.1 ,并且我连接了另外三台计算机,我希望它返回 IP 地址192.168.1.2192.168.1.3192.168.1.4和可能是他们的主机名。

If by "local" you mean on the same network segment, then you have to perform the following steps:如果“本地”是指在同一网段上,则必须执行以下步骤:

  1. Determine your own IP address确定自己的 IP 地址
  2. Determine your own netmask确定自己的网络掩码
  3. Determine the network range确定网络范围
  4. Scan all the addresses (except the lowest, which is your network address and the highest, which is your broadcast address).扫描所有地址(除了最低的,这是您的网络地址,最高的,这是您的广播地址)。
  5. Use your DNS's reverse lookup to determine the hostname for IP addresses which respond to your scan.使用 DNS 的反向查找来确定响应扫描的 IP 地址的主机名。

Or you can just let Python execute nmap externally and pipe the results back into your program.或者你可以让 Python 在外部执行 nmap 并将结果通过管道传回你的程序。

Update : The script is now located on github .更新:该脚本现在位于github 上

I wrote a small python script , that leverages scapy 's arping() .我写了一个小的 python 脚本,它利用了scapyarping()

If you know the names of your computers you can use:如果您知道您的计算机的名称,您可以使用:

import socket
IP1 = socket.gethostbyname(socket.gethostname()) # local IP adress of your computer
IP2 = socket.gethostbyname('name_of_your_computer') # IP adress of remote computer

Otherwise you will have to scan for all the IP addresses that follow the same mask as your local computer (IP1), as stated in another answer.否则,您将不得不扫描与本地计算机 (IP1) 具有相同掩码的所有 IP 地址,如另一个答案中所述。

I have collected the following functionality from some other threads and it works for me in Ubuntu.我从其他一些线程中收集了以下功能,它在 Ubuntu 中对我有用。

import os
import socket    
import multiprocessing
import subprocess


def pinger(job_q, results_q):
    """
    Do Ping
    :param job_q:
    :param results_q:
    :return:
    """
    DEVNULL = open(os.devnull, 'w')
    while True:

        ip = job_q.get()

        if ip is None:
            break

        try:
            subprocess.check_call(['ping', '-c1', ip],
                                  stdout=DEVNULL)
            results_q.put(ip)
        except:
            pass


def get_my_ip():
    """
    Find my IP address
    :return:
    """
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect(("8.8.8.8", 80))
    ip = s.getsockname()[0]
    s.close()
    return ip


def map_network(pool_size=255):
    """
    Maps the network
    :param pool_size: amount of parallel ping processes
    :return: list of valid ip addresses
    """
    
    ip_list = list()
    
    # get my IP and compose a base like 192.168.1.xxx
    ip_parts = get_my_ip().split('.')
    base_ip = ip_parts[0] + '.' + ip_parts[1] + '.' + ip_parts[2] + '.'
    
    # prepare the jobs queue
    jobs = multiprocessing.Queue()
    results = multiprocessing.Queue()
    
    pool = [multiprocessing.Process(target=pinger, args=(jobs, results)) for i in range(pool_size)]
    
    for p in pool:
        p.start()
    
    # cue hte ping processes
    for i in range(1, 255):
        jobs.put(base_ip + '{0}'.format(i))
    
    for p in pool:
        jobs.put(None)
    
    for p in pool:
        p.join()
    
    # collect he results
    while not results.empty():
        ip = results.get()
        ip_list.append(ip)

    return ip_list


if __name__ == '__main__':

    print('Mapping...')
    lst = map_network()
    print(lst)

For OSX (and Linux), a simple solution is to use either os.popen or os.system and run the arp -a command.对于 OSX(和 Linux),一个简单的解决方案是使用 os.popen 或 os.system 并运行arp -a命令。

For example:例如:

devices = []
for device in os.popen('arp -a'): devices.append(device)

This will give you a list of the devices on your local network.这将为您提供本地网络上的设备列表。

I found this network scanner in python article and wrote this short code.在 python 文章中找到了这个网络扫描仪并写了这个短代码。 It does what you want!它做你想做的! You do however need to know accessible ports for your devices.但是,您确实需要知道设备的可访问端口。 Port 22 is ssh standard and what I am using.端口 22 是 ssh 标准和我正在使用的。 I suppose you could loop over all ports.我想你可以遍历所有端口。 Some defaults are:一些默认值是:

linux: [20, 21, 22, 23, 25, 80, 111, 443, 445, 631, 993, 995]
windows: [135, 137, 138, 139, 445]
mac: [22, 445, 548, 631]
import socket

def connect(hostname, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    socket.setdefaulttimeout(1)
    result = sock.connect_ex((hostname, port))
    sock.close()
    return result == 0

for i in range(0,255):
    res = connect("192.168.1."+str(i), 22)
    if res:
        print("Device found at: ", "192.168.1."+str(i) + ":"+str(22))

EDIT by TheLizzard: TheLizzard编辑

Using the code above and adding threading:使用上面的代码并添加线程:

from threading import Thread, Lock
from time import perf_counter
from sys import stderr
from time import sleep
import socket


# I changed this from "192.168.1.%i" to "192.168.0.%i"
BASE_IP = "192.168.0.%i"
PORT = 80


class Threader:
    """
    This is a class that calls a list of functions in a limited number of
    threads. It uses locks to make sure the data is thread safe.
    Usage:
        from time import sleep

        def function(i):
            sleep(2)
            with threader.print_lock:
                print(i)

        threader = Threader(10) # The maximum number of threads = 10
        for i in range(20):
            threader.append(function, i)
        threader.start()
        threader.join()

    This class also provides a lock called: `<Threader>.print_lock`
    """
    def __init__(self, threads=30):
        self.thread_lock = Lock()
        self.functions_lock = Lock()
        self.functions = []
        self.threads = []
        self.nthreads = threads
        self.running = True
        self.print_lock = Lock()

    def stop(self) -> None:
        # Signal all worker threads to stop
        self.running = False

    def append(self, function, *args) -> None:
        # Add the function to a list of functions to be run
        self.functions.append((function, args))

    def start(self) -> None:
        # Create a limited number of threads
        for i in range(self.nthreads):
            thread = Thread(target=self.worker, daemon=True)
            # We need to pass in `thread` as a parameter so we
            # have to use `<threading.Thread>._args` like this:
            thread._args = (thread, )
            self.threads.append(thread)
            thread.start()

    def join(self) -> None:
        # Joins the threads one by one until all of them are done.
        for thread in self.threads:
            thread.join()

    def worker(self, thread:Thread) -> None:
        # While we are running and there are functions to call:
        while self.running and (len(self.functions) > 0):
            # Get a function
            with self.functions_lock:
                function, args = self.functions.pop(0)
            # Call that function
            function(*args)

        # Remove the thread from the list of threads.
        # This may cause issues if the user calls `<Threader>.join()`
        # But I haven't seen this problem while testing/using it.
        with self.thread_lock:
            self.threads.remove(thread)


start = perf_counter()
# I didn't need a timeout of 1 so I used 0.1
socket.setdefaulttimeout(0.1)

def connect(hostname, port):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        result = sock.connect_ex((hostname, port))
    with threader.print_lock:
        if result == 0:
            stderr.write(f"[{perf_counter() - start:.5f}] Found {hostname}\n")

threader = Threader(10)
for i in range(255):
    threader.append(connect, BASE_IP%i, PORT)
threader.start()
threader.join()
print(f"[{perf_counter() - start:.5f}] Done searching")
input("Press enter to exit.\n? ")

Try:尝试:

import socket

print ([ip for ip in socket.gethostbyname_ex(socket.gethostname())[2] if not ip.startswith("127.")][:1])

I have done following code to get the IP of MAC known device.我已经完成了以下代码来获取 MAC 已知设备的 IP。 This can be modified accordingly to obtain all IPs with some string manipulation.这可以进行相应的修改,以通过一些字符串操作来获取所有 IP。 Hope this will help you.希望这会帮助你。

#running windows cmd line  statement and put output into a string
cmd_out = os.popen("arp -a").read()
line_arr = cmd_out.split('\n')
line_count = len(line_arr)


#search in all lines for ip
for i in range(0, line_count):
    y = line_arr[i]
    z = y.find(mac_address)

    #if mac address is found then get the ip using regex matching
    if z > 0:
        ip_out= re.search('[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', y, re.M | re.I)

I have just had the problem.我刚刚遇到了这个问题。 I solved it like this:我是这样解决的:

import kthread #pip install kthread
from time import sleep
import subprocess

def getips():
    ipadressen = {}
    def ping(ipadresse):
        try:
            outputcap = subprocess.run([f'ping', ipadresse, '-n', '1'], capture_output=True) #sends only one package, faster
            ipadressen[ipadresse] = outputcap
        except Exception as Fehler:
            print(Fehler)
    t = [kthread.KThread(target = ping, name = f"ipgetter{ipend}", args=(f'192.168.0.{ipend}',)) for ipend in range(255)] #prepares threads
    [kk.start() for kk in t] #starts 255 threads
    while len(ipadressen) < 255:
        print('Searching network')
        sleep(.3)
    alldevices = []
    for key, item in ipadressen.items():
        if not 'unreachable' in item.stdout.decode('utf-8') and 'failure' not in item.stdout.decode('utf-8'): #checks if there wasn't neither general failure nor 'unrechable host'
            alldevices.append(key)
    return alldevices

allips = getips() #takes 1.5 seconds on my pc

One of the answers in this question might help you. 此问题中的一个答案可能会对您有所帮助。 There seems to be a platform agnostic version for python, but I haven't tried it yet. python似乎有一个与平台无关的版本,但我还没有尝试过。

Here is a small tool scanip that will help you to get all ip addresses and their corresponding mac addresses in the network (Works on Linux).这是一个小工具scanip ,可以帮助您获取网络中的所有ip地址及其对应的mac地址(适用于Linux)。

https://github.com/vivkv/scanip https://github.com/vivkv/scanip

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM