feat(udp): summary command completed
This commit is contained in:
		| @@ -9,9 +9,10 @@ WORKDIR /server | ||||
|  | ||||
| # Create files with random content in the /server directory | ||||
| RUN mkdir /server_directory | ||||
| # these files is only 750 bytes | ||||
|  | ||||
| # These files is only 750 bytes, can fit inside a UDP/TCP packet | ||||
| RUN dd if=/dev/urandom of=/server_directory/file_server.txt bs=1 count=750 | ||||
| RUN dd if=/dev/urandom of=/server_directory/image_server.png bs=1 count=750 | ||||
|  | ||||
| # Start your Python application | ||||
| #CMD python server.py --port_number 12000 --debug 1 | ||||
| # generate a file that has random numbers | ||||
| RUN for _ in $(seq 1 150); do shuf -i 0-1000 -n 1 >> /server_directory/numbers.txt; done | ||||
|   | ||||
							
								
								
									
										150
									
								
								server_directory/numbers.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								server_directory/numbers.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| 970 | ||||
| 408 | ||||
| 627 | ||||
| 774 | ||||
| 374 | ||||
| 425 | ||||
| 292 | ||||
| 570 | ||||
| 681 | ||||
| 971 | ||||
| 141 | ||||
| 468 | ||||
| 271 | ||||
| 120 | ||||
| 450 | ||||
| 298 | ||||
| 802 | ||||
| 34 | ||||
| 448 | ||||
| 979 | ||||
| 181 | ||||
| 117 | ||||
| 322 | ||||
| 885 | ||||
| 733 | ||||
| 31 | ||||
| 818 | ||||
| 582 | ||||
| 83 | ||||
| 524 | ||||
| 104 | ||||
| 285 | ||||
| 932 | ||||
| 964 | ||||
| 292 | ||||
| 306 | ||||
| 621 | ||||
| 584 | ||||
| 109 | ||||
| 302 | ||||
| 555 | ||||
| 250 | ||||
| 2 | ||||
| 59 | ||||
| 602 | ||||
| 452 | ||||
| 357 | ||||
| 404 | ||||
| 486 | ||||
| 37 | ||||
| 616 | ||||
| 667 | ||||
| 154 | ||||
| 938 | ||||
| 552 | ||||
| 887 | ||||
| 969 | ||||
| 602 | ||||
| 701 | ||||
| 284 | ||||
| 358 | ||||
| 37 | ||||
| 802 | ||||
| 290 | ||||
| 1 | ||||
| 94 | ||||
| 829 | ||||
| 854 | ||||
| 678 | ||||
| 938 | ||||
| 156 | ||||
| 466 | ||||
| 420 | ||||
| 391 | ||||
| 757 | ||||
| 22 | ||||
| 843 | ||||
| 346 | ||||
| 658 | ||||
| 330 | ||||
| 383 | ||||
| 274 | ||||
| 229 | ||||
| 537 | ||||
| 444 | ||||
| 14 | ||||
| 656 | ||||
| 646 | ||||
| 616 | ||||
| 357 | ||||
| 930 | ||||
| 975 | ||||
| 626 | ||||
| 964 | ||||
| 497 | ||||
| 860 | ||||
| 290 | ||||
| 558 | ||||
| 714 | ||||
| 969 | ||||
| 496 | ||||
| 871 | ||||
| 667 | ||||
| 148 | ||||
| 262 | ||||
| 424 | ||||
| 402 | ||||
| 337 | ||||
| 770 | ||||
| 61 | ||||
| 899 | ||||
| 153 | ||||
| 567 | ||||
| 129 | ||||
| 922 | ||||
| 12 | ||||
| 375 | ||||
| 810 | ||||
| 658 | ||||
| 991 | ||||
| 399 | ||||
| 820 | ||||
| 198 | ||||
| 25 | ||||
| 17 | ||||
| 696 | ||||
| 885 | ||||
| 307 | ||||
| 254 | ||||
| 600 | ||||
| 508 | ||||
| 983 | ||||
| 703 | ||||
| 175 | ||||
| 363 | ||||
| 197 | ||||
| 831 | ||||
| 998 | ||||
| 534 | ||||
| 833 | ||||
| 291 | ||||
| 434 | ||||
| 218 | ||||
| 858 | ||||
| 795 | ||||
| 140 | ||||
| 102 | ||||
| 170 | ||||
| 182 | ||||
| 992 | ||||
| @@ -112,6 +112,10 @@ class Client: | ||||
|                         f"myftp> - {self.protocol} - Summary file {filename} from the server" | ||||
|                     ) if self.debug else None | ||||
|  | ||||
|                     first_byte = (summary_request_opcode << 5) + len(filename) | ||||
|  | ||||
|                     second_byte_to_n_byte = filename.encode("ascii") | ||||
|  | ||||
|                 # change command handling | ||||
|                 elif change_command_pattern.match(command): | ||||
|                     command_name, old_filename, new_filename = command.split() | ||||
| @@ -125,7 +129,7 @@ class Client: | ||||
|                     first_byte: int = unknown_request_opcode << 5 | ||||
|  | ||||
|                 # get or put case | ||||
|                 if command_name == "get": | ||||
|                 if command_name == "get" or command_name == "summary": | ||||
|                     payload = first_byte.to_bytes(1, "big") + second_byte_to_n_byte  # type: ignore | ||||
|  | ||||
|                 elif command_name == "put": | ||||
| @@ -135,9 +139,6 @@ class Client: | ||||
|                         else first_byte.to_bytes(1, "big")  # type: ignore | ||||
|                     ) | ||||
|  | ||||
|                 elif command_name == "summary": | ||||
|                     pass | ||||
|  | ||||
|                 elif command == "change": | ||||
|                     pass | ||||
|  | ||||
|   | ||||
| @@ -124,6 +124,20 @@ class Server: | ||||
|                         filename = None | ||||
|                         response_data = None | ||||
|  | ||||
|                 elif request_type == "summary": | ||||
|                     # empty filename error | ||||
|                     if filename_length_in_bytes <= 0: | ||||
|                         rescode = rescode_fail_dict["file_not_error_rescode"] | ||||
|                     else: | ||||
|                         ( | ||||
|                             rescode, | ||||
|                             filename,  # "summary.txt" | ||||
|                             filename_length_in_bytes,  # of the summary file | ||||
|                             response_data,  # summary.txt file content | ||||
|                         ) = self.process_summary_req( | ||||
|                             filename_length_in_bytes, req_payload[1:] | ||||
|                         ) | ||||
|  | ||||
|                 elif request_type == "unknown": | ||||
|                     rescode = rescode_fail_dict["unknown_request_rescode"] | ||||
|                     filename_length_in_bytes = None | ||||
| @@ -174,6 +188,64 @@ class Server: | ||||
|  | ||||
|         return request_type, filename_length_in_bytes | ||||
|  | ||||
|     def process_summary_req( | ||||
|         self, filename_length: int, req_payload: bytes | ||||
|     ) -> Tuple[int, Optional[str], Optional[int], Optional[bytes]]: | ||||
|         """ | ||||
|         Find the filename mentioned | ||||
|         Calculate the min,max,avg | ||||
|         Put those numbers into a file called summary.txt | ||||
|         """ | ||||
|         filename = req_payload[:filename_length].decode("ascii") | ||||
|  | ||||
|         print( | ||||
|             f"myftp> - {self.protocol} - Summarizing the file named {filename} on the server" | ||||
|         ) | ||||
|  | ||||
|         try: | ||||
|             with open(os.path.join(self.directory_path, filename), "r") as file: | ||||
|                 numbers = [int(line.strip()) for line in file if line.strip().isdigit()] | ||||
|  | ||||
|                 # Find the largest, smallest, and calculate the average | ||||
|                 largest_number = max(numbers) | ||||
|                 smallest_number = min(numbers) | ||||
|                 average_value = sum(numbers) / len(numbers) if numbers else 0 | ||||
|  | ||||
|                 print( | ||||
|                     f"myftp> - {self.protocol} - File {filename} summarized successfully. The max is {largest_number}, the min is {smallest_number}, the average is {average_value}" | ||||
|                 ) | ||||
|  | ||||
|                 with open( | ||||
|                     os.path.join(self.directory_path, "summary.txt"), "w" | ||||
|                 ) as summary_file: | ||||
|                     summary_file.write(f"min: {smallest_number}\n") | ||||
|                     summary_file.write(f"max: {largest_number}\n") | ||||
|                     summary_file.write(f"avg: {average_value}\n") | ||||
|  | ||||
|                 print( | ||||
|                     f"myftp> - {self.protocol} - Created file summary.txt summarized successfully. Sending it back to the client" | ||||
|                 ) | ||||
|  | ||||
|                 with open( | ||||
|                     os.path.join(self.directory_path, "summary.txt"), "rb" | ||||
|                 ) as summary_file: | ||||
|                     binary_content = summary_file.read() | ||||
|  | ||||
|                 return ( | ||||
|                     rescode_success_dict["correct_summary_request_rescode"], | ||||
|                     "summary.txt", | ||||
|                     11, | ||||
|                     binary_content, | ||||
|                 ) | ||||
|  | ||||
|         except Exception as error: | ||||
|             traceback_info = traceback.format_exc() | ||||
|  | ||||
|             print(f"myftp> - {self.protocol} - {error} happened.") | ||||
|  | ||||
|             print(traceback_info) | ||||
|             return rescode_fail_dict["file_not_error_rescode"], None, None, None | ||||
|  | ||||
|     def process_put_req(self, filename_length: int, req_payload: bytes) -> int: | ||||
|         """ | ||||
|         Reconstruct file put by client | ||||
|   | ||||
		Reference in New Issue
	
	Block a user