diff --git a/buffer.py b/buffer.py index 5dca9f8115fbfab193a1c3389da510af7fdf6d72..e3911be2e4032317a7884c24080d4d0d2049121e 100644 --- a/buffer.py +++ b/buffer.py @@ -26,6 +26,7 @@ class FileBuffer: with open(filename, 'wb') as f: for seg in segments: data = seg.get_data() + print(data[:10]) f.write(data) return diff --git a/client.py b/client.py index 321b6613fea47d8675c68eead0e034d5f5e9ea11..4be6e27a27c6bee02a2eceaaeb79b7511c399a08 100644 --- a/client.py +++ b/client.py @@ -1,6 +1,7 @@ import socket import sys from common import * +from buffer import FileBuffer class Client(): @@ -10,9 +11,14 @@ class Client(): self.init_socket() self.broadcast() - self.handshake() - self.recv_file() - self.close_con() + try: + self.handshake() + self.recv_file() + self.close_con() + self.save_file() + except ConnectionError: + log("!", "Connecion error.") + pass def init_socket(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) @@ -67,43 +73,57 @@ class Client(): def recv_file(self): # To-Do - rcvd = Segment() - base = 0 # antrian ngirim data data_ret = b'' log("!", f"Waiting for server to send data") - + segments = [] while True: data, server_addr = self.recv() # nerima data dari server file_received = self.FILEPATH # deklarasi buat tempat penyimpanan berkas + rcvd = Segment() rcvd.from_bytes(data) # unwrap the data - if rcvd.test_checksum() and rcvd.get_seq_no == base: # untuk ngecek valid checksumnya dan memastikan ini urutan awal + if rcvd.test_checksum() and rcvd.get_seq_no() == base: # untuk ngecek valid checksumnya dan memastikan ini urutan awal if rcvd.isData(): # check jika segmennya bertipe data ack_segment = Segment() ack_segment.setACK() ack_segment.set_seq_no(0) - ack_segment.set_ack_no(rcvd.get_seq_no+1) + ack_segment.set_ack_no(rcvd.get_seq_no()) self.send(ack_segment.to_bytes(), server_addr) - log(f"Segment SEQ={rcvd.get_seq_no()}: Received {rcvd.isData()}, Sent {ack_segment.getACK()}") + log("!", f"Segment SEQ={rcvd.get_seq_no()}: Received {rcvd.isData()}, Sent {ack_segment.getACK()}") data_ret += ack_segment.get_data() - + print(rcvd.bytes[12:22]) + segments.append(rcvd) else: - log(f"Data is empty") + log("!", f"Data is empty") base += 1 elif rcvd.getFIN(): - finack_segment = Segment() - finack_segment.set_seq_no(0) - finack_segment.set_ack_no(0) - finack_segment.setFIN() - finack_segment.setACK() - self.send(finack_segment.to_bytes(), server_addr) + # break, will go to close_con + log("!", "Closing Connection ...") + seg = Segment(300, rcvd.get_seq_no()) + seg.setACK() + self.send(seg.to_bytes(), self.DST_ADDR) + log(f"Segment SEQ={rcvd.get_seq_no()}, FIN", "Received, Ack sent") + + seg = Segment(seg.get_seq_no()) + seg.setFIN() + self.send(seg.to_bytes(), self.DST_ADDR) + log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Sent") + + byte, _ = self.recv() + rcvd = Segment().from_bytes(byte) + if (not rcvd.test_checksum()) or (not rcvd.getACK()) \ + or (rcvd.get_ack_no() != seg.get_seq_no()): + raise ConnectionError + log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Acked") + # self.socket.close() + self.segments = segments break elif not rcvd.test_checksum() or rcvd.get_seq_no() > base: @@ -115,7 +135,7 @@ class Client(): log("!", f"WARNING!!! Segment refused") - elif rcvd.get_seq_no < base: + elif rcvd.get_seq_no() < base: ack_segment = Segment() ack_segment.set_seq_no(0) ack_segment.set_ack_no(base) @@ -123,42 +143,52 @@ class Client(): self.send(ack_segment.to_bytes(), server_addr) log("!", f"WARNING!!! Segment already received") + break # ini mau void apa mau return data_ret yakk wkwkkwkwkwkwk return def close_con(self): # To-Do - log("!", "Closing Connection ...") - - byte, _ = self.recv() - rcvd = Segment().from_bytes(byte) - if (not rcvd.test_checksum()) or (not rcvd.getFIN()): - raise ConnectionError - seg = Segment(300, rcvd.get_seq_no()) - seg.setACK() - self.send(seg.to_bytes(), self.DST_ADDR) - log(f"Segment SEQ={rcvd.get_seq_no()}, FIN", "Received, Ack sent") - - seg = Segment(seg.get_seq_no()) - seg.setFIN() - self.send(seg.to_bytes(), self.DST_ADDR) - log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Sent") - byte, _ = self.recv() - rcvd = Segment().from_bytes(byte) - if (not rcvd.test_checksum()) or (not rcvd.getACK()) \ - or (rcvd.get_ack_no() != seg.get_seq_no()): - raise ConnectionError - log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Acked") - # self.socket.close() + # byte, _ = self.recv() + # rcvd = Segment().from_bytes(byte) + # if (not rcvd.test_checksum()) or (not rcvd.getFIN()): + # raise ConnectionError + # seg = Segment(300, rcvd.get_seq_no()) + # seg.setACK() + # self.send(seg.to_bytes(), self.DST_ADDR) + # log(f"Segment SEQ={rcvd.get_seq_no()}, FIN", "Received, Ack sent") + + # seg = Segment(seg.get_seq_no()) + # seg.setFIN() + # self.send(seg.to_bytes(), self.DST_ADDR) + # log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Sent") + + # byte, _ = self.recv() + # rcvd = Segment().from_bytes(byte) + # if (not rcvd.test_checksum()) or (not rcvd.getACK()) \ + # or (rcvd.get_ack_no() != seg.get_seq_no()): + # raise ConnectionError + # log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Acked") + # # self.socket.close() return + def save_file(self): + fb = FileBuffer() + fb.write(self.segments, self.FILEPATH) + if __name__=="__main__": - try: - port=int(sys.argv[1]) - Client(port=port) - except KeyboardInterrupt: - pass - except : + # try: + # port=int(sys.argv[1]) + # Client(port=port) + # except KeyboardInterrupt: + # pass + # except : + # Client() + if len(sys.argv) > 2: + Client(port=int(sys.argv[1])) + elif len(sys.argv) > 1: + Client(port=int(sys.argv[1])) + else : Client() \ No newline at end of file diff --git a/server.py b/server.py index 0240bccd0b92b4b74dcc55c74022d248f3c87dc6..f33a0b47d4fd5126a40d4b56bdcc080194ea56c4 100644 --- a/server.py +++ b/server.py @@ -2,19 +2,22 @@ import socket import sys import os from common import * +from buffer import FileBuffer +from typing import List class Server(): - def __init__(self, port=10000, filepath="data/halo.txt"): + def __init__(self, port=10000, filepath="data/calender.pdf"): self.SERVER_PORT = port self.FILE_PATH = filepath self.clients = [] + self.N = 1 self.init_socket() self.listen() for client in self.clients : self.handshake(client) - # self.send_file(client) + self.send_file(client) self.close_con(client) def init_socket(self): @@ -51,6 +54,7 @@ class Server(): choice = input() if choice == "n": print() + self.socket.settimeout(3) break def handshake(self, client_addr): @@ -84,22 +88,65 @@ class Server(): def send_file(self, client_addr): # To-Do - file_size = os.path.getsize(self.FILE_PATH) - - with open(self.FILE_PATH, "rb") as f: - file = f.read() - log("!", "File is loaded") - - segments = Segment() - - log("!", f"File segmented into {len(file) // SEG_SIZE} segments") - - self.send(self.FILE_PATH + f"-{file_size}", client_addr) - log("!", "File path and size sent") - - print() + print("====") + print(self.FILE_PATH) + print("===") + list_of_segments = FileBuffer().read(self.FILE_PATH) + count = len(list_of_segments) + log("!", f"File segmented into {count} segments") + + base = 0 + timeout = 0 + while True: + for i in range(self.N): + if (base+i) < count: + print("======") + print(base+i) + seg = list_of_segments[base+i] + seg.set_seq_no(base+i) + self.send(seg.to_bytes(), client_addr) + log(f"Segment SEQ={seg.get_seq_no()}", "Sent") + try: + byte, _ = self.recv() + rcvd = Segment().from_bytes(byte) + if rcvd.test_checksum() and rcvd.get_ack_no() == base: + print(list_of_segments[base].bytes[12:22]) + log(f"Segment SEQ={rcvd.get_seq_no()}", "Acked") + base += 1 + if base >= count: + break + timeout = 0 + except socket.timeout: + log("!", "Connection timeout. ") + timeout += 1 + if timeout == 3: + raise ConnectionError +# ''' +# | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | +# ^ ^ +# function sender is +# Sb := 0 +# Sm := N + 1 +# while True: +# if you receive an ack number where Rn > Sb then +# Sm := (Sm − Sb) + Rn +# Sb := Rn +# if no packet is in transmission then +# Transmit packets where Sb ≤ Sn ≤ Sm. +# Packets are transmitted in order + + +# function receiver is +# Rn := 0 +# Do the following forever: +# if Sn = Rn and the packet is error free then +# Accept the packet and send it to a higher layer +# Rn := Rn + 1 +# else +# Refuse packet +# Send acknowledgement for last received packet +# ''' - return True def close_con(self, client_addr): # To-Do @@ -110,7 +157,7 @@ class Server(): seg = Segment(100) seg.setFIN() self.send(seg.to_bytes(), client_addr) - log(f"Segment SEQ={seg.get_seq_no()}, FIN", "") + log(f"Segment SEQ={seg.get_seq_no()}, FIN", "Sent") byte , _ = self.recv() rcvd = Segment().from_bytes(byte) @@ -130,7 +177,15 @@ class Server(): return True if __name__=="__main__": - try: - Server(port=sys.argv[1], filepath=sys.argv[2]); - except: - Server(); \ No newline at end of file + # try: + # Server(port=int(sys.argv[1]), filepath=sys.argv[2]); + # except: + # log("!", "Using another port") + # Server(filepath=sys.argv[2]); + if len(sys.argv) > 2: + Server(port=int(sys.argv[1]), filepath=sys.argv[2]); + elif len(sys.argv) > 1: + Server(port=int(sys.argv[1])) + else : + Server() +