code: def multi_ping(dest_addrs, timeout, retry=0, ignore_lookup_errors=False):
      
      retry = int(retry)
      if retry < 0:
          retry = 0
  
      timeout = float(timeout)
      if timeout < 0.1:
          raise MultiPingError("Timeout < 0.1 seconds not allowed")
  
      retry_timeout = float(timeout) / (retry + 1)
      if retry_timeout < 0.1:
          raise MultiPingError("Time between ping retries < 0.1 seconds")
  
      mp = MultiPing(dest_addrs, ignore_lookup_errors=ignore_lookup_errors)
  
      results = {}
      retry_count = 0
      while retry_count <= retry:
          # Send a batch of pings
          mp.send()
          single_results, no_results = mp.receive(retry_timeout)
          # Add the results from the last sending of pings to the overall results
          results.update(single_results)
          if not no_results:
              # No addresses left? We are done.
              break
          retry_count += 1
  
      return results, no_results
docs: Combine send and receive measurement into single function.
  
      This offers a retry mechanism: Overall timeout time is divided by
      number of retries. Additional ICMPecho packets are sent to those
      addresses from which we have not received answers, yet.
  
      The retry mechanism is useful, because individual ICMP packets may get
      lost.
  
      If 'retry' is set to 0 then only a single packet is sent to each
      address.
  
      If 'ignore_lookup_errors' is set then any issues with resolving target
      names or looking up their address information will silently be ignored.
      Those targets simply appear in the 'no_results' return list.