2

Assuming you got something like this (copied from here):

#!/usr/bin/python
from scapy.all import *

TIMEOUT = 2
conf.verb = 0
for ip in range(0, 256):
    packet = IP(dst="192.168.0." + str(ip), ttl=20)/ICMP()
    reply = sr1(packet, timeout=TIMEOUT)
    if not (reply is None):
         print reply.src, "is online"
    else:
         print "Timeout waiting for %s" % packet[IP].src

There is no need to wait for each ping to finish before trying the next host. Could I put the loop interior each time into the background along the lines of the & in:

for ip in 192.168.0.{0..255}; do 
ping -c 1 $ip &
done
Community
  • 1
  • 1
user857990
  • 1,140
  • 3
  • 14
  • 29
  • 4
    Beside the point, but are you aware that `range(0,255)` ends at `254`? – Tim Pietzcker Sep 16 '13 at 12:43
  • thanks for the typo correction – user857990 Sep 16 '13 at 12:46
  • 1
    You could use the [`concurrent.futures`](http://docs.python.org/3/library/concurrent.futures.html#module-concurrent.futures) module to do pings concurrently. – Fred Foo Sep 16 '13 at 12:48
  • You should use some asynchronous library, or select. Also, `reply is not None` looks better than `not (reply is None)`. ;) – Bunyk Sep 16 '13 at 12:49
  • You can actually provide a range of IP addresses to capy, and it will send out accordingly, you can then evaluate the results of sr separately, which would work a lot faster as there should be less I/O blocks. – KillianDS Sep 16 '13 at 12:52

2 Answers2

5

The first thing you should do is change your range to range(0, 256) so that it is inclusive of 0-255.

Second, you're looking at Python's threading, which can be somewhat similar to Bash process daemonization at an abstract level.

Import multiprocessing and create a pool:

from multiprocessing.pool import ThreadPool
pool = ThreadPool(20)  # However many you wish to run in parallel

So take the ping lookup, which is everything inside of the for loop, and make it a function.

def ping(ip):
    packet = IP(dst="192.168.0." + str(ip), ttl=20)/ICMP()
    reply = sr1(packet, timeout=TIMEOUT)
    if not (reply is None):
         print reply.src, "is online"
    else:
         print "Timeout waiting for %s" % packet[IP].src

Then in your for loop,

for ip in range(0, 256):
    pool.apply_async(ping, (ip,))

pool.close()
pool.join()

pool.join() is what waits for all of your threads to return.

Jordan
  • 31,971
  • 6
  • 56
  • 67
0

You can use threading or multiprocessing module to run aynchronous/non-blocking IO calls.

Read about hte difference on SO:

multiprocess or threading in python?

Community
  • 1
  • 1
btel
  • 5,563
  • 6
  • 37
  • 47