def start(self): ''' Main loop. continue receiving messages from Clients and processing it ''' threads = {} #Dictionary for multi-threading #Main loop while True: receiveMessage, address = self.sock.recvfrom(4096) messageType, sequenceNumber, breakMessage, _ = util.parse_packet(receiveMessage.decode("utf-8")) sendSequence = int(sequenceNumber) + 1 #If the checksum of the received packet is valid if util.validate_checksum(receiveMessage.decode("utf-8")): #If we get a start packet initialize a new queue for that respective client and make a thread of process_handler for it and send ack packet to client if messageType == "start": self.receive_start(address, sendSequence, threads) #If we get a data packet send ack packet to client and wait for next packet elif messageType == "data": self.receive_data(address, sendSequence, breakMessage) #If we get a end packet we will delete the thread from the dictionary elif messageType == "end": self.receive_end(address, sendSequence, threads) #If we receive ack message from client we will update acknowledged and send the next packet to the client in send function elif messageType == "ack": self.receive_ack(address, sendSequence)
def construct_message(self, all_packets): ''' leave out end and start packets and make complete message from the packets recieved ''' packets_to_use = len(all_packets) - 1 msg = "" for i in range(1, packets_to_use): p_type, seqno, data, checksum = util.parse_packet(all_packets[i]) msg = msg + data return msg
def listener(thread_quit, port): ''' Fungsi utama yang mendengarkan semua pesan masuk Exclusive access ke port yang diatur Args: thread_quit (threading.Event) : Signaling untuk memberitahu jika thread selesai port (int) : Port number untuk dibind ''' # Setup socket listener_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) listener_socket.setblocking(False) listener_socket.bind(("", port)) while (not thread_quit.is_set()): try: data, addr = listener_socket.recvfrom(MAX_LENGTH_DATA + LENGTH_TYPE_ID + LENGTH_CHECKSUM + LENGTH_LENGTH + LENGTH_SEQUENCE) packet_data = parse_packet(data) data_type = packet_data["type"] if data_type != PacketType.INVALID: source_address = addr[0] data_ID = packet_data["id"] # Jika Data atau FIN buat thread listener, jika tidak passing ke thread sender if data_type == PacketType.DATA or data_type == PacketType.FIN: if thread_pool_listener.get(source_address) == None: thread_pool_listener[source_address] = [None] * 16 if thread_pool_listener[source_address][data_ID] == None: handler = Queue() thread_pool_listener[source_address][data_ID] = handler threading.Thread(target=receive_thread, args=((source_address, port), handler)).start() handler.put(packet_data) else: thread_pool_listener[source_address][data_ID].put( packet_data) else: if (thread_pool_sender[source_address][data_ID] != None): thread_pool_sender[source_address][data_ID].put( packet_data) except socket.error: pass listener_socket.close()
def receive_handler(self): ''' Waits for a message from server and process it accordingly ''' global stop #To stop the main loop #Main loop while not stop: revieveMessage, address = self.sock.recvfrom(self.server_port) _, _, breakMessage, _ = util.parse_packet( revieveMessage.decode("utf-8")) breakMessage = breakMessage.split() #If the clients request to join has been rejected if breakMessage[0].strip() == "join": print(breakMessage[2]) #If the clients request for active user list has been processed elif breakMessage[0].strip() == "response_users_list": print("list:", " ".join(breakMessage[2:])) #If someone has send a message elif breakMessage[0].strip() == "forward_message": print("msg:", " ".join(breakMessage[2:])) #If someone has send a file elif breakMessage[0].strip() == "forward_file": fileName = breakMessage[3] fileData = " ".join(breakMessage[4:]) print("file:", breakMessage[2] + ":", fileName) fileName = self.name + "_" + fileName fileHandle = open(fileName, "w") fileHandle.write(fileData) fileHandle.close() #If the server is full elif breakMessage[0].strip() == "err_server_full": print("disconnected: server full") stop = True self.sock.close() #If the username is already taken elif breakMessage[0].strip() == "err_username_unavailable": print("disconnected: username not available") stop = True self.sock.close() #If the client send an unknown message format elif breakMessage[0].strip() == "err_unknown_message": print("disconnected: server received an unknown command") stop = True self.sock.close()
def start(self): ''' Main loop. continue receiving messages from Clients and processing it ''' global transfer global acknowledged global nextSeqNumber global acknowledgedAddress threads = {} #Dictionary for multi-threading #Main loop while True: receiveMessage, address = self.sock.recvfrom(4094) messageType, sequenceNumber, breakMessage, _ = util.parse_packet( receiveMessage.decode("utf-8")) sendSequence = int(sequenceNumber) + 1 #If we get a start packet initialize a new queue for that respective client and make a thread of process_handler for it and send ack packet to client if messageType == "start": transfer[address] = queue.Queue() threads[address] = Thread(target=self.process_handler, args=(address, )) threads[address].daemon = True threads[address].start() sendPacket = util.make_packet( "ack", sendSequence, ) self.sock.sendto(sendPacket.encode("utf-8"), address) #If we get a data packet send ack packet to client and wait for next packet elif messageType == "data": transfer[address].put(breakMessage) sendPacket = util.make_packet( "ack", sendSequence, ) self.sock.sendto(sendPacket.encode("utf-8"), address) #If we get a end packet we will delete the thread from the dictionary elif messageType == "end": transfer[address].put(messageType) del threads[address] #If we receive ack message from client we will update acknowledged and send the next packet to the client in send function elif messageType == "ack": nextSeqNumber = int(sequenceNumber) acknowledgedAddress = address acknowledged = True
def start(self): ''' Main loop. continue receiving messages from Clients and processing it ''' while True: packet, addr = self.sock.recvfrom(4096) #initialize buffers for every new request if addr not in self.ack_buffer or addr not in self.ack_queue: self.ack_buffer[addr] = -1 self.ack_queue[addr] = queue.Queue(maxsize=1) p_type, seqno, message, checksum = util.parse_packet( packet.decode("utf-8")) #if the packet is ack store in buffer if p_type == "ack": self.ack_buffer[addr] = int(seqno) q = self.ack_queue[addr] q.put(int(seqno)) #create a buffer for the incoming address if addr not in self.packet_buff: self.packet_buff[addr] = {} #store the packets in the buffer if p_type != "ack": self.packet_buff[addr][int(seqno)] = packet.decode("utf-8") ##checks whether complete packets were recieved or not tmp = message.split() #dont send acknowledgment for acknowledgment if p_type != "ack": self.send_ack(packet, addr) if (p_type == "end"): # every time and end packet is received # it means that all data has bess received # hence to process that data a new thread is made so that # main thread never gets blocked processDataThread = Thread(target=self.processAndServe, args=(addr, )) processDataThread.daemon = True processDataThread.start()
def receive_handler(self): ''' Waits for a message from server and process it accordingly ''' while True: packet = self.sock.recv(util.CHUNK_SIZE) packet = packet.decode('utf-8') message = util.parse_packet(packet)[2] msg = message.split(' ') if 'ERR_SERVER_FULL' in msg[0]: print(msg[2]) self.sock.close() os._exit(1) elif 'ERR_USERNAME_UNAVAILABLE' in msg[0]: print(msg[2]) self.sock.close() os._exit(1) elif 'response_list' in msg[0]: msg1 = msg[2].replace('$', " ") print(f"list: {msg1}") elif 'FORWARD' in msg[0]: msg1 = ' '.join(msg[2:]) msg1 = msg1.replace(' ', ' ') print(msg1) elif 'DISCONNECT' in msg[0]: print('disconnected: server received a unknown command') self.sock.close() os._exit(1) elif 'forward_file' in msg[0]: client = msg[2] file = msg[3] data = msg[4].replace('[s]', ' ').replace('[nl]', '\n') with open(f'{client}_{file}', 'w+') as f: f.write(data) f.close() print(f'file: {client}: {file}')
def waitAndreSend(self, packet, addr): ''' in the case of single packet transmission, send the packet and then wait for its acknowledgemtn if the ack is recieved within 0.5 ms then good, otherwise resend packer ''' msg_type, seqno, message, checksum = util.parse_packet(packet) pack_n = int(seqno) + 1 sent = False resend = 5 while sent == False and resend > 0: try: ackbuf = self.ack_queue[addr] ack = ackbuf.get(timeout=0.5) sent = True except: resend = resend - 1 self.send_res(packet, addr)
def start(self): ''' Main loop. continue receiving messages from Clients and processing it ''' clientUsername = [] #Will store the usernames of the clients clientData = { } #Will store the address of the clients with usernames as the key usernameExists = False #Boolian variable to check if the username is already taken or not clientConnected = 0 #Variable to track the number of clients connected sendMessage = "" #The message that will be made sendPacket = "" #The packer that will be send #Main loop while True: #Recieve the message, parse it and break into list revieveMessage, address = self.sock.recvfrom(4096) _, _, breakMessage, _ = util.parse_packet( revieveMessage.decode("utf-8")) breakMessage = breakMessage.split() #Check if the client has sent the join message if breakMessage[0].strip() == "join": #Check if the maximum client limit has been reached if clientConnected == util.MAX_NUM_CLIENTS: self.send(address, "err_server_full", 2) print("disconnected: server full") #If the client limit has not been reached else: #Traverse the client username list to check if the username is already taken for username in clientUsername: #If the username already exits if breakMessage[2].strip() == username.strip(): self.send(address, "err_server_full", 2) usernameExists = True print("disconnected: username not available") break #If the username does not exist if not usernameExists: clientUsername.append(breakMessage[2]) clientUsername.sort(key=str.casefold) clientData[breakMessage[2]] = address clientConnected += 1 print("join:", breakMessage[2]) usernameExists = False #Check if the client has requested the active users list elif breakMessage[0].strip() == "request_users_list": print("request_users_list:", util.get_key(clientData, address)) listCompile = "" #Traverse the client username list for username in clientUsername: listCompile += username + " " self.send(address, "response_users_list", 3, listCompile) #Check if the client wants to send the message elif breakMessage[0].strip() == "send_message": #Check if the message does not contain a character on <numberOfClients> part if not breakMessage[3].isdigit(): self.send(address, "err_unknown_message", 2) print("disconnected:", util.get_key(clientData, address)) #Check if the number of usernames enters is not less than specified in the message elif len(breakMessage) - 4 <= int(breakMessage[3]): self.send(address, "err_unknown_message", 2) print("disconnected:", util.get_key(clientData, address)) #If no format error else: print("msg:", util.get_key(clientData, address)) end = int(breakMessage[3]) + 4 #Traverse through the usernames to which client wants to send the message to for i in range(4, end): #The destination username exits if clientData.get(breakMessage[i]) is not None: message = util.get_key(clientData, address) + ": " + " ".join( breakMessage[end:]) destinationAddress = ((clientData.get( breakMessage[i]))[0], (clientData.get( breakMessage[i]))[1]) self.send(destinationAddress, "forward_message", 4, message) #The destination username does not exits else: print("msg:", util.get_key(clientData, address), "to non-existent user", breakMessage[i]) #Check if the client wants to send a file elif breakMessage[0].strip() == "send_file": #Check if the message does not contain a character on <numberOfClients> part if not breakMessage[3].isdigit(): self.send(address, "err_unknown_message", 2) print("disconnected:", util.get_key(clientData, address)) #If there is no format error else: print("file:", util.get_key(clientData, address)) end = int(breakMessage[3]) + 4 #Traverse through the usernames to which client wants to send the message to for i in range(4, end): #The destination username exits if clientData.get(breakMessage[i]) is not None: message = util.get_key(clientData, address) + " " + " ".join( breakMessage[end:]) destinationAddress = ((clientData.get( breakMessage[i]))[0], (clientData.get( breakMessage[i]))[1]) self.send(destinationAddress, "forward_file", 4, message) #The destination username does not exits else: print("file:", util.get_key(clientData, address), "to non-existent user", breakMessage[i]) #Check if the client wants to disconnet elif breakMessage[0].strip() == "disconnect": clientUsername.remove(breakMessage[2]) clientData.pop(breakMessage[2]) clientConnected -= 1 print("disconnected:", breakMessage[2]) #If the format recieved is something unknown else: print("disconnected:", util.get_key(clientData, address), "sent unknown command") self.send(address, "err_unknown_message", 2)
def receive_handler(self): ''' Waits for a message from server and process it accordingly ''' while True: start = False end = False # loop from start packet to end packet while (start == False or end == False): packet = self.sock.recv(4096) p_type, seqno, res, checksum = util.parse_packet( packet.decode("utf-8")) if (p_type == "ack"): # store ack in ack buffer self.ack_buffer = int(seqno) self.ack_queue.put(int(seqno), block=True) if p_type != "ack": # if not ack buffer the packer self.packet_buff[int(seqno)] = packet.decode("utf-8") if p_type == "start": start = True if p_type == "end": end = True if p_type != "ack": #send ack for every packet received self.send_ack(packet) #get packets from buffer all_packets = self.getPacketsFromBuffer() # construct full message frm the packets res = self.construct_message(all_packets) #process data here res_unsplit = res res = res.split() res_type = res[0] # max number of client reached if res_type == "err_server_full": # print("disconnected: server full") os._exit(1) # username is already taken or unavailable elif res_type == "err_username_unavailable": # print("disconnected: username not available") os._exit(1) elif res_type == "response_users_list": total_clients = res[2] total_clients = int(total_clients) out = "list:" for i in range(3, total_clients + 3): out = out + " " + res[i] print(out) elif res_type == "forward_message": sender = res[3] recieved_text = '' for i in range(4, len(res)): recieved_text = recieved_text + " " + res[i] recieved_text = recieved_text.strip() print("msg:", sender + ":", recieved_text) elif res_type == "forward_file": sender = res[3] file_recieved = res[4] d = res_unsplit.split("<delimtter>") text = d[1] print("file:", sender + ":", file_recieved) f = open(self.name + "_" + file_recieved, 'w') f.write(text) f.close() elif res_type == "err_unknown_message": os._exit(1) self.resetBuffer() self.reset_ack_queue()
def receive_handler(self): ''' Waits for a message from server and process it accordingly ''' global stop global acknowledged global nextSeqNumber chunks = [] #Main loop while not stop: receiveMessage, address = self.sock.recvfrom(self.server_port) messageType, sequenceNumber, message, _ = util.parse_packet( receiveMessage.decode("utf-8")) #If client recieved the ack packet it will update acknowledged and send the next packet using the send function if messageType == "ack": nextSeqNumber = int(sequenceNumber) acknowledged = True #If client recieves the start packet then it will send ack packet and wait for next packet from the server elif messageType == "start": sendPacket = util.make_packet( "ack", int(sequenceNumber) + 1, ) self.sock.sendto(sendPacket.encode("utf-8"), (self.server_addr, self.server_port)) #If client recieves the data packet it will send ack packet and wait for the next packet from the server elif messageType == "data": chunks.append(message) sendPacket = util.make_packet( "ack", int(sequenceNumber) + 1, ) self.sock.sendto(sendPacket.encode("utf-8"), (self.server_addr, self.server_port)) #If client recieves the end packet it will join all the chunks together and process the message elif messageType == "end": extractMessage = "" #For each chunk recieved concatinate it into message for chunk in chunks: extractMessage += chunk breakMessage = extractMessage.split() #If the clients request to join has been rejected if breakMessage[0].strip() == "join": print(breakMessage[2]) #If the clients request for active user list has been processed elif breakMessage[0].strip() == "response_users_list": print("list:", " ".join(breakMessage[2:])) #If someone has send a message elif breakMessage[0].strip() == "forward_message": print("msg:", " ".join(breakMessage[2:])) #If someone has send a file elif breakMessage[0].strip() == "forward_file": fileName = breakMessage[3] fileData = " ".join(breakMessage[4:]) print("file:", breakMessage[2] + ":", fileName) fileName = self.name + "_" + fileName fileHandle = open(fileName, "w") fileHandle.write(fileData) fileHandle.close() #If the server is full elif breakMessage[0].strip() == "err_server_full": print("disconnected: server full") stop = True self.sock.close() #If the username is already taken elif breakMessage[0].strip() == "err_username_unavailable": print("disconnected: username not available") stop = True self.sock.close() #If the client send an unknown message format elif breakMessage[0].strip() == "err_unknown_message": print("disconnected: server received an unknown command") stop = True self.sock.close() chunks = []
def receive_handler(self): ''' Waits for a message from server and process it accordingly ''' new_msg = '' while True: catch_packet = self.sock.recv(4096).decode("utf-8") msg_type, seq_no, msg, checksum = util.parse_packet(catch_packet) self.seq_no = seq_no print(catch_packet) if msg_type == 'ack': is_ack = True self.q.put(is_ack) print('received an ack put it into the client queue') elif msg_type == 'data': new_msg += msg print('new_msg concatenated') elif msg_type == 'end': msg_list = new_msg.split(' ') new_msg = '' if msg_list[0] == "response_users_list": my_list = [] my_list = msg_list[3:] my_list.sort() str_out = ' '.join(my_list) print('list:', str_out[2:]) elif msg_list[0] == "disconnect": print('disconnected') self.sock.close() sys.exit() return elif msg_list[0] == 'forward_message': print('msg:', msg_list[2] + ':', ' '.join(msg_list[3:])) elif msg_list[0] == 'err_username_unavailable': print('disconnected: username not available') self.sock.close() sys.exit() return elif msg_list[0] == 'err_server_full': print('disconnected: server full') self.sock.close() sys.exit() return elif msg_list[0] == 'err_unknown_message': print('disconnected: server recieved an unknown command') self.sock.close() sys.exit() return elif msg_list[0] == 'forward_file': new_file_name = self.name + '_' + msg_list[3] print('file:', msg_list[2] + ':', msg_list[3]) f = open(new_file_name, "x") f.write(' '.join(msg_list[4:])) f.close() else: if len(new_msg) != 0: print(new_msg)
def receive_handler(self): ''' Waits for a message from server and process it accordingly ''' global STOP chunks = [] #Main loop while not STOP: receiveMessage, _ = self.sock.recvfrom(self.server_port) messageType, sequenceNumber, message, _ = util.parse_packet( receiveMessage.decode("utf-8")) #If the checksum of the received packet is valid if util.validate_checksum(receiveMessage.decode("utf-8")): #If client recieved the ack packet it will update ACKNOWLEDGED and send the next packet using the send function if messageType == "ack": self.receive_ack(sequenceNumber) #If client recieves the start packet then it will send ack packet and wait for next packet from the server elif messageType == "start": self.receive_start(sequenceNumber, chunks) #If client recieves the data packet it will send ack packet and wait for the next packet from the server elif messageType == "data": self.receive_data(sequenceNumber, chunks, message) #If client recieves the end packet it will join all the chunks together and process the message elif messageType == "end": breakMessage = [] #For each chunk recieved concatinate it into message breakMessage = self.receive_end(sequenceNumber, chunks) #If the list is not empty if breakMessage: #If clients asks to join the server if breakMessage[0].strip() == "join": print(breakMessage[2]) #If the clients request for active user list has been processed elif breakMessage[0].strip() == "response_users_list": print("list:", " ".join(breakMessage[2:])) #If someone has send a message elif breakMessage[0].strip() == "forward_message": print("msg:", " ".join(breakMessage[2:])) #If someone has send a file elif breakMessage[0].strip() == "forward_file": fileName = breakMessage[3] fileData = " ".join(breakMessage[4:]) print("file:", breakMessage[2] + ":", fileName) fileName = self.name + "_" + fileName fileHandle = open(fileName, "w") fileHandle.write(fileData) fileHandle.close() #If the server is full elif breakMessage[0].strip() == "err_server_full": print("disconnected: server full") STOP = True self.sock.close() #If the username is already taken elif breakMessage[0].strip( ) == "err_username_unavailable": print("disconnected: username not available") STOP = True self.sock.close() #If the client send an unknown message format elif breakMessage[0].strip() == "err_unknown_message": print( "disconnected: server received an unknown command" ) STOP = True self.sock.close() chunks = []