Advertisement
Guest User

Untitled

a guest
Feb 25th, 2018
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.55 KB | None | 0 0
  1. import sys, asyncio
  2.  
  3. ################
  4. # Server class #
  5. ################
  6.  
  7. class Server:
  8. default_server_address = '127.0.0.1'
  9. default_server_port = 8888
  10.  
  11. # NOTE: you can modify __init__
  12. def __init__(self,server_address=default_server_address,server_port=default_server_port):
  13. self.address = server_address
  14. self.port = server_port
  15. self.all_clients = set([])
  16. self.registered_clients = set([])
  17. self.client_dict={}
  18.  
  19. # NOTE: the following method must be implemented for some of our grading tests to work. If you don't implement this method correctly, you will lose some marks!
  20. # method for registering usernames
  21. def set_username(self,new_username,writer,old_username=None):
  22. registered_users = self.get_registered_usernames_list()
  23. if new_username in registered_users:
  24. print("@client ERROR User already registered")
  25. writer.write("@client ERROR User already registered".encode())
  26. #add client to dictionary and handle changing client's username
  27. else:
  28. if len(self.client_dict.items())>0:
  29. for key, value in self.client_dict.items():
  30. if value == writer:
  31. old_username = key
  32. self.client_dict[new_username]=self.client_dict[old_username]
  33. del self.client_dict[old_username]
  34. print("@client username set to " + new_username)
  35. output = "@client username set to "+new_username
  36. writer.write(output.encode())
  37. self.registered_clients.add(writer)
  38. break
  39. else:
  40. self.client_dict[new_username] = writer
  41. print("@client username set to " + new_username)
  42. output = "@client username set to "+new_username
  43. writer.write(output.encode())
  44. self.registered_clients.add(writer)
  45. break
  46. else:
  47. self.client_dict[new_username] = writer
  48. print("@client username set to " + new_username)
  49. output = "@client username set to "+new_username
  50. writer.write(output.encode())
  51. self.registered_clients.add(writer)
  52.  
  53.  
  54.  
  55.  
  56.  
  57. # NOTE: this method must be implemented for some of our grading tests to work. If you don't implement this method correctly, you will lose some marks!
  58. # method that returns all the registered usernames as a list
  59. def get_registered_usernames_list(self):
  60. return list(self.client_dict.keys())
  61.  
  62. # NOTE: you can modify the implementation of handle_connection (but not its signature)
  63. @asyncio.coroutine
  64. def handle_connection(self, reader, writer):
  65. self.all_clients.add(writer)
  66. client_addr = writer.get_extra_info('peername')
  67. print('New client {}'.format(client_addr))
  68. while True:
  69. data = yield from reader.read(100)
  70. if data == None or len(data) == 0:
  71. break
  72. message = data.decode()
  73. if message.startswith("@server "):
  74. if message.startswith("@server set_my_id(") and message.endswith(")"):
  75. client_name = message[message.find("(") +1:message.find(")")]
  76. self.set_username(client_name,writer)
  77. print(self.registered_clients)
  78. continue
  79. else:
  80. writer.write("@client ERROR Message does not match the username registration format".encode())
  81. continue
  82.  
  83. print("Received {} from {}".format(message, client_addr))
  84. sender = None
  85. for client in self.client_dict:
  86. if self.client_dict[client] == writer:
  87. sender = client
  88. break
  89. if(sender==None):
  90. print("@client ERROR Cannot send messages as an unregistered user")
  91. writer.write("@client ERROR Cannot send messages as an unregistered user".encode())
  92. continue
  93. #sends message to all clients
  94. names = self.get_registered_usernames_list()
  95. is_private = False
  96. for name in names:
  97. if message.startswith("@"+name):
  98. private_writer = self.client_dict[name]
  99. message = message[1:]
  100. sender_name=""
  101. for key, value in self.client_dict.items():
  102. if value == writer:
  103. sender_name = key
  104. index = len(sender_name)
  105. new_message = "#" +sender_name + ':' + message[len(name):]
  106. private_writer.write(new_message.encode())
  107. is_private = True
  108.  
  109. if is_private==False:
  110. for other_writer in self.registered_clients:
  111. if other_writer != writer:
  112. new_message = '{}: {}'.format(sender,data.decode())
  113. other_writer.write(( new_message).encode())
  114.  
  115. yield from other_writer.drain()
  116. print("Closing connection with client {}".format(client_addr))
  117. writer.close()
  118. self.all_clients.remove(writer)
  119. if writer in self.registered_clients:
  120. self.registered_clients.remove(writer)
  121.  
  122.  
  123. # NOTE: do not modify run
  124. def run(self):
  125. loop = asyncio.get_event_loop()
  126. coro = asyncio.start_server(self.handle_connection,self.address,
  127. self.port,loop=loop)
  128. server = loop.run_until_complete(coro)
  129.  
  130. print('Serving on {}'.format(server.sockets[0].getsockname()))
  131. try:
  132. loop.run_forever()
  133. except KeyboardInterrupt:
  134. print('\nGot keyboard interrupt, shutting down',file=sys.stderr)
  135.  
  136. for task in asyncio.Task.all_tasks():
  137. task.cancel()
  138. server.close()
  139. loop.run_until_complete(server.wait_closed())
  140. loop.close()
  141.  
  142.  
  143. # NOTE: do not modify the following two lines
  144. if __name__ == '__main__':
  145. Server().run()
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152. import sys, asyncio
  153. import aioconsole
  154.  
  155. #####################
  156. # Custom exceptions #
  157. #####################
  158.  
  159. class NoneException(Exception):
  160. pass
  161.  
  162. class ClosingException(Exception):
  163. pass
  164.  
  165. ################
  166. # Client class #
  167. ################
  168.  
  169. class Client:
  170. default_server_address = '127.0.0.1'
  171. default_server_port = 8888
  172.  
  173. # NOTE: you can modify __init__
  174. def __init__(self, server_address=default_server_address, server_port=default_server_port):
  175. self.server_address = server_address
  176. self.server_port = server_port
  177. self.name = None # NOTE: do not remove the attribute from your client implementation, but use it to store the registered username associated to this client. This is a pre-condition for some of our grading tests to work correctly.
  178.  
  179. # NOTE: do not modify open_connection
  180. @asyncio.coroutine
  181. def open_connection(self,loop):
  182. reader, writer = yield from asyncio.open_connection(
  183. self.server_address, self.server_port, loop=loop)
  184. return reader, writer
  185.  
  186. # NOTE: do not modify use_connection
  187. @asyncio.coroutine
  188. def use_connection(self,reader, writer):
  189. yield from asyncio.gather(self.read_from_network(reader,writer),
  190. self.send_to_server(writer))
  191.  
  192. # NOTE: you can modify the implementation of read_from_network (but not its signature)
  193. @asyncio.coroutine
  194. def read_from_network(self,reader,writer):
  195. while True:
  196. net_message = yield from reader.read(100)
  197. message = ""
  198.  
  199. if(not isinstance(net_message, str)):
  200. message = net_message.decode()
  201.  
  202.  
  203. if writer.transport.is_closing():
  204. print('Terminating read from network.')
  205. break
  206. elif net_message == None:
  207. continue
  208. elif len(net_message) == 0:
  209. print('The server closed the connection.')
  210. writer.close()
  211. break
  212. elif "@client username set to" in message:
  213. last_word = message.split()
  214. client_name = last_word[-1]
  215. self.name = client_name
  216. print('\n%s' % message)
  217. print('>> ',end='',flush=True)
  218. continue
  219. elif "@client ERROR" in message:
  220. print ("\n[server] " + message[8:])
  221. print('>> ',end='',flush=True)
  222. continue
  223. elif "#" in message:
  224. print('\n[private] %s' % message[1:])
  225. print('>> ',end='',flush=True)
  226.  
  227. else:
  228. print('\n[public] %s' % message)
  229. print('>> ',end='',flush=True)
  230.  
  231. # NOTE: you can modify the implementation of send_to_server (but not its signature)
  232. @asyncio.coroutine
  233. def send_to_server(self,writer):
  234. try:
  235. while True:
  236. original_message = yield from aioconsole.ainput('>> ')
  237. if original_message != None:
  238. console_message = original_message.strip()
  239. if console_message == '':
  240. continue
  241. elif console_message == 'close()':
  242. raise ClosingException()
  243. elif console_message.startswith('@'):
  244. if console_message.startswith("@server"):
  245. if '(' in console_message and ')' in console_message:
  246. client_name = console_message[console_message.find("(") +1:console_message.find(")")]
  247. if(client_name.lower() == "client" or client_name.lower() =="server"):
  248. print("[error]: username cannot be client or server")
  249. continue
  250. elif ' ' in client_name:
  251. print("[error]: username cannot contain spaces")
  252. continue
  253.  
  254. elif console_message.startswith("@"+self.name):
  255. print("[error] Cannot private message yourself")
  256. writer.write(console_message.encode())
  257.  
  258. #elif self.name != none:
  259. # print("[error]:Syntax error when sending username to server")
  260. except ClosingException:
  261. print('Got close() from user.')
  262. finally:
  263. if not writer.transport.is_closing():
  264. writer.close()
  265.  
  266. # NOTE: do not modify run
  267. def run(self):
  268. try:
  269. loop = asyncio.get_event_loop()
  270. reader,writer=loop.run_until_complete(self.open_connection(loop))
  271. loop.run_until_complete(self.use_connection(reader,writer))
  272. except KeyboardInterrupt:
  273. print('Got Ctrl-C from user.')
  274. except Exception as e:
  275. print(e,file=sys.stderr)
  276. finally:
  277. loop.close()
  278.  
  279. # NOTE: do not modify the following two lines
  280. if __name__ == '__main__':
  281. Client().run()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement