From c9e6eefc4d08a56ff8ac944c843a8bbfc8a00119 Mon Sep 17 00:00:00 2001
From: abiwardani <abi.wardani85@gmail.com>
Date: Tue, 23 Nov 2021 23:11:13 +0700
Subject: [PATCH] loop data sending, add savefile, add connection class
---
.DS_Store | Bin 6148 -> 6148 bytes
client.py | 118 +++++++++++++++++++---------
connection.py | 8 ++
server.py | 209 ++++++++++++++++++++++++++++---------------------
test/test1.txt | 1 +
testtest1.txt | 1 +
transmitter.py | 8 +-
7 files changed, 216 insertions(+), 129 deletions(-)
create mode 100644 connection.py
create mode 100644 test/test1.txt
create mode 100644 testtest1.txt
diff --git a/.DS_Store b/.DS_Store
index bd6c3ecaf6cff3fab05e6a8496e4db20b100ab7b..82e45533608ada25774d4d131672d58dd1f46f48 100644
GIT binary patch
delta 49
zcmZoMXfc>@KrJy{X!DX~haDLh7+4re7*ZLE8A@{VQ(TgA@{<@C7&svE8=uLE0|1#z
B5KI67
delta 49
zcmZoMXfc>@KyB;XW+#=UhaDLh7+4re7*ZLE8A@{VQ(TgA@{<@C7&svE8=uLE0|1|&
B5MBTP
diff --git a/client.py b/client.py
index f81a82e..5167e07 100644
--- a/client.py
+++ b/client.py
@@ -1,9 +1,10 @@
import socket
import sys
-import random
import segment
import hexa
import receiver
+from connection import Connection
+import pickle
'''
Pseudocode
@@ -18,6 +19,27 @@ Pseudocode
6. Menutup program
'''
+#--- Client compile file
+def saveFile(segmentPool, folderpath):
+ filename = input("\nSaving file...\n\nFile name: ")
+ if ("." in filename):
+ filename = filename[0:filename.index(".")+1]
+
+ res = ""
+ for s in segmentPool:
+ res += s
+
+ res = hexa.byte(res,'latin-1')
+
+ res = pickle.loads(res)
+ res.name = filename
+
+ f = open(folderpath + "/" + res.name + ".txt", "wb")
+ f.write(res.content)
+ f.close()
+
+#--- Initialize broadcast socket
+
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
host = socket.gethostname()
@@ -26,20 +48,36 @@ print("Host: "+str(host))
if (len(sys.argv) > 1):
port = sys.argv[1]
s.bind(('127.0.0.1', int(port)))
+else:
+ print("Port number not specified. Run: 'python client.py <port-number> </path/to/folder>'")
+ exit()
+
+if (len(sys.argv) > 2):
+ folderpath = sys.argv[2]
+else:
+ print("Folder not specified. Run: 'python client.py <port-number> </path/to/folder>'")
+ exit()
+
+#--- Send broadcast
message = "Hello server"
s.sendto(message.encode(),('127.0.0.1',1337))
print("Sent broadcast: "+message)
+
+
+#--- TCP over UDP, receive file from server
+
fin = False
-server_seq_num = None
-n_data_sent = 0
-n_data_received = 0
+serverConnection = Connection('127.0.0.1', 1337, 0)
stage = "RECEIVE_SYN_SEND_SYN_ACK"
received_data = None
+segmentPool = []
+
while (not(fin)):
+ # 1. client menerima SYN dari server, lalu mengirim SYN-ACK
if (stage == "RECEIVE_SYN_SEND_SYN_ACK"):
data, address = s.recvfrom(32777)
@@ -49,21 +87,21 @@ while (not(fin)):
rec_packet.build(r.receiveSegment(data))
if (r.isSynSegment(rec_packet) and not(r.isAckSegment(rec_packet))):
- #if server send SYN to start connection,
+ #if server send SYN untuk memulai koneksi
seq_num0 = rec_packet.getSeqNum()
- server_seq_num = seq_num0
+ serverConnection.server_seq_num = seq_num0
print("\nSYN received with seq num: "+str(seq_num0))
ack_packet = segment.Segment()
- #--- Nanti set seq_num sama ack_num pake go-back-n ---#
- n_data_received += 1
+ #--- Nanti set seq_num sama ack_num pake go-back-n?? ---#
+ serverConnection.n_data_received += 1
- seq_num = server_seq_num #paket pertama
- ack_num = seq_num0 + n_data_received #ekspektasi: seq_num berikut adalah seq_num + 1
+ seq_num = serverConnection.server_seq_num #paket pertama, random sequence number
+ ack_num = seq_num0 + serverConnection.n_data_received #ekspektasi: seq_num berikut adalah seq_num + 1
- n_data_sent += 1
+ serverConnection.n_data_sent += 1
#--- END ---#
ack_packet.switchFlag("SYN")
@@ -74,9 +112,11 @@ while (not(fin)):
message = hexa.byte(ack_packet.construct(),'utf-8')
s.sendto(message, (address[0], address[1]))
- print("\nSent SYN-ACK with seq_num: "+str(seq_num)+" and ack num: "+str(ack_num))
+ print("\nSYN-ACK sent with seq_num: "+str(seq_num)+" and ack num: "+str(ack_num))
stage = "RECEIVE_ACK"
+
+ # 2. client menerima ACK dari server
elif (stage == "RECEIVE_ACK"):
data, address = s.recvfrom(32777)
@@ -86,17 +126,22 @@ while (not(fin)):
rec_packet.build(r.receiveSegment(data))
if (not(r.isSynSegment(rec_packet)) and r.isAckSegment(rec_packet)):
- #if server send ACK to acknowledge client SYN,
+ #if server mengirim ACK untuk acknowledge client SYN,
seq_num0 = rec_packet.getSeqNum()
ack_num0 = rec_packet.getAckNum()
print("\nACK received with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
- if (seq_num0 == server_seq_num + n_data_received):
+ if (seq_num0 == serverConnection.server_seq_num + serverConnection.n_data_received):
print("\nConnection established, receiving data...")
stage = "RECEIVE_DATA"
+
+ # 3. client menerima data dari server
elif (stage == "RECEIVE_DATA"):
+
+ #--- RECEIVE DATA, belum konkuren ---#
+
data, address = s.recvfrom(32777)
r = receiver.Receiver()
@@ -105,23 +150,25 @@ while (not(fin)):
rec_packet.build(r.receiveSegment(data))
if (r.isDataSegment(rec_packet)):
- #if server send data
+ #if server send data ke client
seq_num0 = rec_packet.getSeqNum()
ack_num0 = rec_packet.getSeqNum()
print("\nData received with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
- if (seq_num0 == server_seq_num + n_data_received): #curr_ack_num masih sama karena sebelum ini, client belum menerima paket dengan payload
+ if (seq_num0 == serverConnection.server_seq_num + serverConnection.n_data_received): #curr_ack_num masih sama karena sebelum ini, client belum menerima paket dengan payload
received_data = rec_packet.getPayLoad()
- print("\nReceived data: "+received_data)
+ print("\nReceived data from server")
+
+ segmentPool.append(received_data)
ack_packet = segment.Segment()
#--- Nanti set seq_num sama ack_num pake go-back-n ---#
- n_data_received += len(received_data) #tambah jumlah bit dalam payload
+ serverConnection.n_data_received += len(received_data) #tambah jumlah bit dalam payload
- seq_num = server_seq_num + n_data_sent
- ack_num = server_seq_num + n_data_received
+ seq_num = serverConnection.server_seq_num + serverConnection.n_data_sent
+ ack_num = serverConnection.server_seq_num + serverConnection.n_data_received
#--- END ---#
ack_packet.switchFlag("ACK")
@@ -131,16 +178,17 @@ while (not(fin)):
message = hexa.byte(ack_packet.construct(),'utf-8')
s.sendto(message, (address[0], address[1]))
- print("\nSent ACK with seq_num: "+str(seq_num)+" and ack num: "+str(ack_num))
+ print("\nACK sent with seq_num: "+str(seq_num)+" and ack num: "+str(ack_num))
- stage = "CLOSE_CONNECTION"
- elif (stage == "CLOSE_CONNECTION"):
- data, address = s.recvfrom(32777)
-
- r = receiver.Receiver()
- rec_packet = segment.Segment()
+ elif (r.isFinSegment(rec_packet)):
+ #if server send FIN
- rec_packet.build(r.receiveSegment(data))
+ saveFile(segmentPool, folderpath)
+
+ stage = "CLOSE_CONNECTION"
+
+ # 4. server menutup koneksi, client mengikuti
+ elif (stage == "CLOSE_CONNECTION"):
if (r.isFinSegment(rec_packet)):
#if server close connection
@@ -149,14 +197,14 @@ while (not(fin)):
print("\nFIN received with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
- if (seq_num0 == server_seq_num + n_data_received):
+ if (seq_num0 == serverConnection.server_seq_num + serverConnection.n_data_received):
ack_packet = segment.Segment()
#--- Nanti set seq_num sama ack_num pake go-back-n ---#
- n_data_received += 1
+ serverConnection.n_data_received += 1
- seq_num = server_seq_num + n_data_sent
- ack_num = server_seq_num + n_data_received
+ seq_num = serverConnection.server_seq_num + serverConnection.n_data_sent
+ ack_num = serverConnection.server_seq_num + serverConnection.n_data_received
#--- END ---#
ack_packet.switchFlag("ACK")
@@ -171,10 +219,10 @@ while (not(fin)):
fin_packet = segment.Segment()
#--- Nanti set seq_num sama ack_num pake go-back-n ---#
- seq_num = server_seq_num + n_data_sent
- ack_num = server_seq_num + n_data_received
+ seq_num = serverConnection.server_seq_num + serverConnection.n_data_sent
+ ack_num = serverConnection.server_seq_num + serverConnection.n_data_received
- n_data_sent += 1
+ serverConnection.n_data_sent += 1
#--- END ---#
fin_packet.switchFlag("FIN")
diff --git a/connection.py b/connection.py
new file mode 100644
index 0000000..51f05bc
--- /dev/null
+++ b/connection.py
@@ -0,0 +1,8 @@
+class Connection:
+ def __init__(self, IP, port, initial_seq_num):
+ self.IP = IP
+ self.port = port
+ self.name = IP+":"+str(port)
+ self.initial_seq_num = initial_seq_num
+ self.n_data_sent = 0
+ self.n_data_received = 0
\ No newline at end of file
diff --git a/server.py b/server.py
index 5858526..a1f45bf 100644
--- a/server.py
+++ b/server.py
@@ -5,6 +5,7 @@ import hexa
import transmitter
import receiver
import random
+from connection import Connection
NUMBERS = ["zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"]
@@ -30,13 +31,20 @@ Pseudocode:
'''
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+
if (len(sys.argv) > 1):
port = int(sys.argv[1])
print("Server started at port "+str(port)+"...")
+else:
+ print("Port number not specified. Run: 'python server.py <port-number> </path/to/file>'")
+ exit()
+if (len(sys.argv) > 2):
+ filepath = sys.argv[2]
else:
- print("Port number not specified. Run: 'python server.py <port-number>'")
+ print("File not specified. Run: 'python server.py <port-number> </path/to/file>'")
exit()
+
s.bind(('127.0.0.1',port))
def listen_broadcast():
@@ -47,7 +55,8 @@ def listen_broadcast():
while True:
data, address = s.recvfrom(1024)
client = str(address[0])+":"+str(address[1])
- clients.append(address)
+ connectionObj = Connection(address[0], address[1], 0)
+ clients.append(connectionObj)
print("[!] Client ("+client+") found")
cont = input("[?] Listen more? (y/n) ").lower()
if (cont == "n" or cont != "y"):
@@ -60,35 +69,40 @@ def listen_broadcast():
def list_clients(clients):
print(NUMBERS[len(clients)].title()+" clients found:")
for i in range(len(clients)):
- print(str(i+1)+". "+str(clients[i][0])+":"+str(clients[i][1]))
+ print(str(i+1)+". "+str(clients[i].IP)+":"+str(clients[i].port))
return clients
-def send_and_connect(clients):
+def send_and_connect(clients, filepath):
print("\nCommencing file transfer...")
+ # server menghubungi setiap client dan mengirim filenya
for client in clients:
- connect(client)
+ connect(client, filepath)
-def connect(client):
- IP = client[0]
- port = client[1]
+ print("\n\nFiles sent. Closing connection...\n")
+
+ # server mengakhiri hubungan dengan setiap client
+ for client in clients:
+ closeConnection(client)
+
+def connect(clientConnection, filepath):
+ IP = clientConnection.IP
+ port = clientConnection.port
stage = "SEND_SYN"
server_seq_num = random.randint(0, 4294967295)
- n_data_sent = 0
- n_data_received = 0
+ clientConnection.server_seq_num = server_seq_num
fin = False
while not(fin):
+ # 1. server kirim SYN ke client untuk memulai koneksi
if (stage == "SEND_SYN"):
- #send SYN
-
syn_packet = segment.Segment()
seq_num = server_seq_num #kirim random secure integer sebagai seq_num awal server
#--- Nanti set seq_num sama ack_num pake go-back-n ---#
- n_data_sent += 1 #tambah satu karena mengirim paket SYN (kalo paket ACK saja tidak diinkremen)
+ clientConnection.n_data_sent += 1 #tambah satu karena mengirim paket SYN (kalo paket ACK saja tidak diinkremen)
#--- END ---#
syn_packet.switchFlag("SYN")
@@ -97,7 +111,11 @@ def connect(client):
message = hexa.byte(syn_packet.construct(),'utf-8')
s.sendto(message, (IP, port))
+ print("\nSYN sent to client "+IP+":"+str(port)+" with seq num: "+str(seq_num))
+
stage = "RECEIVE_SYN_ACK_SEND_ACK"
+
+ # 2. server menerima SYN-ACK dari client, lalu mengirim ACK untuk acknowledge SYN tersebut
elif (stage == "RECEIVE_SYN_ACK_SEND_ACK"):
data, address = s.recvfrom(32777)
rec_packet = segment.Segment()
@@ -114,11 +132,10 @@ def connect(client):
ack_packet = segment.Segment()
#--- Nanti set seq_num sama ack_num pake go-back-n ---#
- n_data_received += 1 #diinkremen karena menerima paket SYN
+ clientConnection.n_data_received += 1 #diinkremen karena menerima paket SYN
- seq_num = server_seq_num + n_data_sent
- ack_num = server_seq_num + n_data_received
- curr_ack_num = ack_num
+ seq_num = server_seq_num + clientConnection.n_data_sent
+ ack_num = server_seq_num + clientConnection.n_data_received
#--- END ---#
ack_packet.switchFlag("ACK")
@@ -132,115 +149,127 @@ def connect(client):
stage = "SEND_FILE"
+ # 3. server mengirim file
elif (stage == "SEND_FILE"):
print("\nSending file...")
- tm = transmitter.Transmitter(server_seq_num + n_data_received)
- tm.prepareSegment("./test.txt")
+ tm = transmitter.Transmitter(server_seq_num + clientConnection.n_data_received)
+ tm.prepareSegment(filepath)
- message = tm.transmitSegment(0)
- s.sendto(message, (IP, port))
+ #--- SLIDING WINDOW, belum konkuren ---#
+ for i in range(len(tm.segmentQueue)):
- r = receiver.Receiver()
- rec_packet = segment.Segment()
+ #--- DRAFT TRANSMIT ---#
+ message = tm.transmitSegment(i) #kirim segmen ke-i
+ s.sendto(message, (IP, port))
- rec_packet.build(r.receiveSegment(data))
- n_data_sent += len(tm.segmentQueue[0].getPayLoad())
+ clientConnection.n_data_sent += len(tm.segmentQueue[i].getPayLoad())
+ #--- END ---#
- stage = "FIN"
- elif (stage == "FIN"):
- data, address = s.recvfrom(32777)
- rec_packet = segment.Segment()
- r = receiver.Receiver()
+ #--- DRAFT RECEIVE ACK, belum konkuren ---#
+ data, address = s.recvfrom(32777)
+ rec_packet = segment.Segment()
+ r = receiver.Receiver()
- rec_packet.build(r.receiveSegment(data))
+ rec_packet.build(r.receiveSegment(data))
- if (r.isAckSegment(rec_packet)):
- #server receive ACK of file sent
- seq_num0 = rec_packet.getSeqNum()
- ack_num0 = rec_packet.getAckNum()
+ if (r.isAckSegment(rec_packet)):
+ #server receive ACK of file sent
+ seq_num0 = rec_packet.getSeqNum()
+ ack_num0 = rec_packet.getAckNum()
- print("\nACK received from client "+address[0]+":"+str(address[1])+" with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
+ print("\nACK received from client "+address[0]+":"+str(address[1])+" with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
+
+ #--- SLIDING WINDOW ---#
- if ((address[0] == IP) and (address[1] == port)):
- print("\nClosing connection with client: "+IP+":"+str(port))
+ # 4. urusan sudah selesai, server berhenti mengirim koneksi
- #server send FIN to close connection
-
- fin_packet = segment.Segment()
+ fin = True
- #--- Nanti set seq_num sama ack_num pake go-back-n ---#
- seq_num = server_seq_num + n_data_sent
- ack_num = server_seq_num + n_data_received
-
- n_data_sent += 1
- #--- END ---#
- fin_packet.switchFlag("FIN")
- fin_packet.setSeqNum(seq_num)
- fin_packet.setAckNum(ack_num)
+def closeConnection(clientConnection):
+ IP = clientConnection.IP
+ port = clientConnection.port
+ server_seq_num = clientConnection.server_seq_num
+ fin = False
- message = hexa.byte(fin_packet.construct(), 'utf-8')
- s.sendto(message, (IP, port))
+ #--- CLOSING ---#
- print("\nFIN sent to client "+IP+":"+str(port)+" with seq num: "+str(seq_num)+" and ack_num: "+str(ack_num))
+ print("\nClosing connection with client: "+IP+":"+str(port))
- data, address = s.recvfrom(32777)
- rec_packet = segment.Segment()
- r = receiver.Receiver()
+ #server send FIN to close connection
- rec_packet.build(r.receiveSegment(data))
+ fin_packet = segment.Segment()
- if (r.isAckSegment(rec_packet)):
- #server receive ACK of server's FIN
+ seq_num = server_seq_num + clientConnection.n_data_sent
+ ack_num = server_seq_num + clientConnection.n_data_received
+
+ clientConnection.n_data_sent += 1
- if ((address[0] == IP) and (address[1] == port)):
- seq_num0 = rec_packet.getSeqNum()
- ack_num0 = rec_packet.getAckNum()
+ fin_packet.switchFlag("FIN")
+ fin_packet.setSeqNum(seq_num)
+ fin_packet.setAckNum(ack_num)
- print("\nACK received from client "+address[0]+":"+str(address[1])+" with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
+ message = hexa.byte(fin_packet.construct(), 'utf-8')
+ s.sendto(message, (IP, port))
- data, address = s.recvfrom(32777)
- rec_packet = segment.Segment()
- r = receiver.Receiver()
+ print("\nFIN sent to client "+IP+":"+str(port)+" with seq num: "+str(seq_num)+" and ack_num: "+str(ack_num))
+
+ while (fin != True):
+ data, address = s.recvfrom(32777)
+ rec_packet = segment.Segment()
+ r = receiver.Receiver()
+
+ rec_packet.build(r.receiveSegment(data))
+
+ if (r.isAckSegment(rec_packet)):
+ #server receive ACK of server's FIN
+ if ((address[0] == IP) and (address[1] == port)):
+ seq_num0 = rec_packet.getSeqNum()
+ ack_num0 = rec_packet.getAckNum()
+
+ print("\nACK received from client "+address[0]+":"+str(address[1])+" with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
- rec_packet.build(r.receiveSegment(data))
+ data, address = s.recvfrom(32777)
+ rec_packet = segment.Segment()
+ r = receiver.Receiver()
- if (r.isFinSegment(rec_packet)):
- #sender receive FIN to close connection
- seq_num0 = rec_packet.getSeqNum()
- ack_num0 = rec_packet.getAckNum()
+ rec_packet.build(r.receiveSegment(data))
- print(address)
+ if (r.isFinSegment(rec_packet)):
+ #sender receive FIN to close connection
+ seq_num0 = rec_packet.getSeqNum()
+ ack_num0 = rec_packet.getAckNum()
- if ((address[0] == IP) and (address[1] == port)):
- #if correct client wants to close
+ if ((address[0] == IP) and (address[1] == port)):
+ #if correct client wants to close
- print("\nFIN received from client "+address[0]+":"+str(address[1])+" with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
+ print("\nFIN received from client "+address[0]+":"+str(address[1])+" with seq num: "+str(seq_num0)+" and ack num: "+str(ack_num0))
- ack_packet = segment.Segment()
+ ack_packet = segment.Segment()
- #--- Nanti set seq_num sama ack_num pake go-back-n ---#
- n_data_received += 1
+ #--- Nanti set seq_num sama ack_num pake go-back-n ---#
+ clientConnection.n_data_received += 1
- seq_num = server_seq_num + n_data_sent
- ack_num = server_seq_num + n_data_received
- #--- END ---#
+ seq_num = server_seq_num + clientConnection.n_data_sent
+ ack_num = server_seq_num + clientConnection.n_data_received
+ #--- END ---#
- ack_packet.switchFlag("ACK")
- ack_packet.setSeqNum(seq_num)
- ack_packet.setAckNum(ack_num)
+ ack_packet.switchFlag("ACK")
+ ack_packet.setSeqNum(seq_num)
+ ack_packet.setAckNum(ack_num)
- message = hexa.byte(ack_packet.construct(), 'utf-8')
- s.sendto(message, (IP, port))
+ message = hexa.byte(ack_packet.construct(), 'utf-8')
+ s.sendto(message, (IP, port))
- print("\nACK sent to client "+IP+":"+str(port)+" with seq_num: "+str(seq_num)+" and ack_num: "+str(ack_num))
+ print("\nACK sent to client "+IP+":"+str(port)+" with seq_num: "+str(seq_num)+" and ack_num: "+str(ack_num))
- fin = True #close connection
+ fin = True #close connection
- print("\nConnection with client "+IP+":"+str(port)+" closed.")
+ print("\nConnection with client "+IP+":"+str(port)+" closed.")
+#--- Main ---#
clients = listen_broadcast()
-send_and_connect(clients)
+send_and_connect(clients, filepath)
diff --git a/test/test1.txt b/test/test1.txt
new file mode 100644
index 0000000..0c7d9ca
--- /dev/null
+++ b/test/test1.txt
@@ -0,0 +1 @@
+hello world byte
\ No newline at end of file
diff --git a/testtest1.txt b/testtest1.txt
new file mode 100644
index 0000000..0c7d9ca
--- /dev/null
+++ b/testtest1.txt
@@ -0,0 +1 @@
+hello world byte
\ No newline at end of file
diff --git a/transmitter.py b/transmitter.py
index a205c7d..a074cde 100644
--- a/transmitter.py
+++ b/transmitter.py
@@ -16,7 +16,7 @@ class Transmitter:
- segmentQueue : queue of segments
'''
self.segmentQueue = []
- self.counter_start = counter_start
+ self.counter = counter_start
def prepareSegment(self,filePath : str):
'''
@@ -27,14 +27,14 @@ class Transmitter:
'''
handler = filehandler.FileHandler()
fileHexString = handler.dumpFile(filePath)
- counter = self.counter_start
for i in range(0,len(fileHexString),segment.PAYLOAD_MAX_HEXLENGTH):
s = segment.Segment()
- s.setSeqNum(counter)
+ s.setSeqNum(self.counter)
s.loadPayLoad(fileHexString[i:i + segment.PAYLOAD_MAX_HEXLENGTH])
s.switchFlag("DATA")
self.segmentQueue.append(s)
- counter += 1
+ self.counter += len(s.getPayLoad())
+ print(self.counter)
def transmitSegment(self,index : int) -> bytes:
'''
--
GitLab