forma optimizada de search una dirección IP de dispositivo dentro de un range en el iPhone

Tengo una situación en la que tengo que search la dirección IP del enrutador ** y sé que solo su range es del range 163.289.2.0 a 163.289.2.255. Sé que esta no es una buena forma de search.

for i in 1... 255 { var str = "163.289.2." + "i" var tempIP = Ping.getIPAddress(str) if(tempIP == true) { break; } } 

Ahora mi problema es mi class personalizada Ping.getIPAddress () tarda 3 segundos para get el resultado para un valor de IP dado. Entonces, para 255 búsquedas, toma aproximadamente 765 segundos (12.75 minutos). Tengo una restricción que la búsqueda debe completar en máximo 2 minutos. Así que, de todos modos, puedo lograr esto en iPhone usando swift.

Debo usar solo esta function personalizada Ping.getIPAddress () que da true si la dirección IP dada es más falsa.

Proporcione un ejemplo o reference o enfoque para resolver este problema.

¿Será bueno utilizar NSOperationQueue con MaxConcurrentOperationCount establecido en 10?

Enfoque síncrono

Si realizamos cada llamada a Ping.getIPAddress(str) solo después de que la anterior se haya completado, por supuesto, debemos esperar (3 segundos * 256) = 768 segundos.

introduzca la descripción de la imagen aquí

Enfoque asynchronous

Por otro lado, podemos realizar varias llamadas simultáneas a Ping.getIPAddress(str) .

introduzca la descripción de la imagen aquí

La class falsa de ping

Esta es una class que creé para probar tu function.

 class Ping { class func getIPAddress(str:String) -> Bool { sleep(3) return str == "163.289.2.255" } } 

Como ves, la class espera 3 segundos (para simular tu escenario) y luego devuelve true solo si el ip pasado es 163.289.2.255 . Esto me permite replicar el peor de los casos.

Solución

Esta es la class que preparé

 class QuantumComputer { func search(completion:(existingIP:String?) -> ()) { var resultFound = false var numProcessed = 0 let serialQueue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL) for i in 0...255 { dispatch_async(dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)) { var ip = "163.289.2." + "\(i)" let foundThisOne = Ping.getIPAddress(ip) dispatch_async(serialQueue) { if !resultFound { resultFound = foundThisOne numProcessed++ if resultFound { completion(existingIP:ip) } else if numProcessed == 256 { completion(existingIP: nil) } } } } } } } 

La class realiza 256 llamadas asíncronas a Ping.getIPAddress(...) .

Los resultados de los cierres asíncronos 256 son procesados ​​por este código:

 dispatch_async(serialQueue) { if !resultFound { resultFound = foundThisOne numProcessed++ if resultFound { completion(existingIP:ip) } else if numProcessed == 256 { completion(existingIP: nil) } } } 

El bloque de código anterior (de la línea n. ° 2 a n. ° 9) se ejecuta en mi queue serialQueue . Aquí los 256 cierres distintos se ejecutan sincrónicamente .

  1. esto es crucial para garantizar un acceso consistente a las variables resultFound y numProcessed ;
  2. por otro lado, este no es un problema por el punto de vista del performance , ya que este código es bastante rápido (solo un montón de operaciones aritméticas)

Prueba

Y así es como lo llamo desde un ViewController estándar.

 class ViewController: UIViewController { var computer = QuantumComputer() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. debugPrintln(NSDate()) computer.search { (existingIP) -> () in debugPrintln("existingIP: \(existingIP)") debugPrintln(NSDate()) } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } } 

Conclusiones

Finalmente, este es el resultado cuando lo pruebo en mi simulador de iOS. Recuerde que este es el peor escenario (ya que el último número marcado es un IP válido).

 2015-09-04 20:56:17 +0000 "existingIP: Optional(\"163.289.2.255\")" 2015-09-04 20:56:29 +0000 

¡Son solo 12 segundos!

Espero que esto ayude.