client.py 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #!/usr/bin/env python
  2. import socket
  3. import select
  4. import random
  5. import subprocess
  6. import time
  7. import re
  8. import peerfinder_pb2 as pf
  9. SERVER = ("::1", 9999)
  10. # In seconds
  11. HEARTBEAT_INTERVAL = random.randint(5, 15)
  12. RECONNECT_INTERVAL = random.randint(5, 15)
  13. NB_PINGS = 3
  14. ping_regexp = re.compile(r"time=(.*) ms")
  15. def ping(target, nb_pings=NB_PINGS):
  16. """Returns the list of latencies towards the given target"""
  17. args = ["ping", "-n", "-c", str(nb_pings), str(target.address)]
  18. try:
  19. out = subprocess.check_output(args, shell=False)
  20. except subprocess.CalledProcessError:
  21. return []
  22. data = out.decode("utf8").split("\n")
  23. data = [ping_regexp.search(line) for line in data]
  24. return [float(m.group(1)) for m in data if m != None]
  25. def run_measurements(s):
  26. while True:
  27. try:
  28. data = s.recv(1024)
  29. print(data)
  30. if len(data) == 0:
  31. s.close()
  32. return
  33. msg = pf.Message()
  34. msg.ParseFromString(data)
  35. if msg.type == pf.Message.Pong:
  36. print("Got pong")
  37. else:
  38. target = msg.target
  39. latencies = ping(target.target)
  40. reply = pf.Message()
  41. reply.type = pf.Message.Measurement
  42. reply.measurement.target_id = msg.target.target_id
  43. reply.measurement.probes_sent = NB_PINGS
  44. reply.measurement.probes_received = len(latencies)
  45. reply.measurement.latency_us.extend([int(1000 * l) for l in latencies])
  46. s.send(reply.SerializeToString())
  47. except socket.timeout:
  48. print("Sending heartbeat")
  49. msg = pf.Message()
  50. msg.type = pf.Message.Ping
  51. s.send(msg.SerializeToString())
  52. except ConnectionResetError:
  53. s.close()
  54. return
  55. if __name__ == '__main__':
  56. while True:
  57. sock = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
  58. sock.settimeout(HEARTBEAT_INTERVAL)
  59. try:
  60. sock.connect(SERVER)
  61. print("Connected to {}".format(SERVER))
  62. run_measurements(sock)
  63. except ConnectionRefusedError:
  64. pass
  65. print("Disconnected, reconnecting in {} seconds".format(RECONNECT_INTERVAL))
  66. time.sleep(RECONNECT_INTERVAL)