listing27-3.py 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. from xmlrpc.client import ServerProxy, Fault
  2. from cmd import Cmd
  3. from random import choice
  4. from string import ascii_lowercase
  5. from server import Node, UNHANDLED
  6. from threading import Thread
  7. from time import sleep
  8. import sys
  9. HEAD_START = 0.1 # Seconds
  10. SECRET_LENGTH = 100
  11. def random_string(length):
  12. """
  13. Returns a random string of letters with the given length.
  14. """
  15. chars = []
  16. letters = ascii_lowercase[:26]
  17. while length > 0:
  18. length -= 1
  19. chars.append(choice(letters))
  20. return ''.join(chars)
  21. class Client(Cmd):
  22. """
  23. A simple text-based interface to the Node class.
  24. """
  25. prompt = '> '
  26. def __init__(self, url, dirname, urlfile):
  27. """
  28. Sets the url, dirname, and urlfile, and starts the Node
  29. Server in a separate thread.
  30. """
  31. Cmd.__init__(self)
  32. self.secret = random_string(SECRET_LENGTH)
  33. n = Node(url, dirname, self.secret)
  34. t = Thread(target=n._start)
  35. t.setDaemon(1)
  36. t.start()
  37. # Give the server a head start:
  38. sleep(HEAD_START)
  39. self.server = ServerProxy(url)
  40. for line in open(urlfile):
  41. line = line.strip()
  42. self.server.hello(line)
  43. def do_fetch(self, arg):
  44. "Call the fetch method of the Server."
  45. try:
  46. self.server.fetch(arg, self.secret)
  47. except Fault as f:
  48. if f.faultCode != UNHANDLED: raise
  49. print("Couldn't find the file", arg)
  50. def do_exit(self, arg):
  51. "Exit the program."
  52. print()
  53. sys.exit()
  54. do_EOF = do_exit # End-Of-File is synonymous with 'exit'
  55. def main():
  56. urlfile, directory, url = sys.argv[1:]
  57. client = Client(url, directory, urlfile)
  58. client.cmdloop()
  59. if __name__ == '__main__': main()