feat(udp): summary command completed
This commit is contained in:
parent
73b4e06d02
commit
fe23170908
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user