def le_do_buffer(udp, nome_arquivo): id_pacote = 1 global fila_de_pacotes # Como estamos utilizando para testes, caso o arquivo já exista # sobrescrevemos o conteúdo do mesmo arquivo = open(nome_arquivo,'w') arquivo.close() while True: if(len(fila_de_pacotes) == 0 or len(fila_de_pacotes) == buffer_size): continue else: arquivo = abre_arquivo_escrita(nome_arquivo) pacote = fila_de_pacotes.popleft() if(pacote.get_sequencial() == id_pacote): #Insere o arquivo em ordem arquivo.write(pacote.get_dado()) id_pacote = id_pacote + 1 else:#Esta fora da ordem fila_de_pacotes.append(pacote) fecha_arquivo(arquivo)
def le_dados_arquivo(file_name, tamanho_pcte, tamanho_arquivo): deslocamento = 0 qtd_pctes = 1 global fila_de_pacotes, pacotes_a_enviar #Percorre o arquivo até o final while deslocamento < tamanho_arquivo: if(len(fila_de_pacotes) == buffer_size): #Tamanho máximo da fila continue else: # Realiza o deslocamento até o ponto correto do arquivo file_name.seek(deslocamento) # Lê os dados para montar o pacote buf = file_name.read(tamanho_pcte) checksum = gera_md5(buf) # Cria o pacote e o insere na fila de pacotes pacote = Pacote(qtd_pctes, buf,checksum) fila_de_pacotes.append(pacote) qtd_pctes = qtd_pctes + 1 #Incrementa a quantidade de pacotes deslocamento = deslocamento + 1460 pacotes_a_enviar = len(fila_de_pacotes) fecha_arquivo(file_name)
def recebe_pacotes(udp,nome_arquivo): #Definição das variáveis globaix global fila_de_pacotes print 'Para sair use CTRL + c\n' NFE = 1 pacotes_confirmados = deque([]) while True: pacote, cliente = udp.recvfrom(1560) #Só ocorrerá na primeira mensagem ou no fim' if(len(pacote) < 40 and len(pacote) != 1): #Pois somente o cabeçalho já tem 40 bytes, jamais um pacote terá tamanho menor que 40 string = 'c i 16s' pacote = struct.unpack(string, pacote) if(pacote[0] == 'w' or pacote[0] == 'g' or pacote[0] == 'a'): flag = pacote[0] pacotes_a_receber = int(pacote[1]) checksum_arquivo = pacote[2] udp.sendto('OK', cliente) # Envia para o cliente que está configurado continue elif(pacote == 'c'): #Lê os dados do arquivo e verifica o checksum arquivo = abre_arquivo_leitura(nome_arquivo) buf = arquivo.read() checksum_final = gera_md5(buf) if(checksum_final == checksum_arquivo): status = 'OK' else: status = 'ERRO' print 'Enviando status do arquivo escrito no disco' udp.sendto(status, cliente) fecha_arquivo(arquivo) continue else: tamanho_pcte = len(pacote) - 40 # Calcula o tamanho do pacote - o cabeçalho tamanho_pcte = str(tamanho_pcte) string = '10s 10s 16s i ' + tamanho_pcte + 's' #Monta a string que será utilizada para unpack pacote = struct.unpack(string, pacote) #ACK = randomico(pacote[3], taxa) ACK = pacote[3] #if (ACK != 0): ''' Na atual implementação, os pacotes só chegarão sequencialmente, por isso o go-back-n e o stop-and-wait tem o mesmo receptor ''' if(flag == 'w' or flag == 'g'): if(ACK < NFE or ACK in pacotes_confirmados): #Reenvia o ACK pois o pacote já foi recebido ACK = str(ACK) udp.sendto(ACK, cliente) else: if(ACK == NFE): checksum = gera_md5(pacote[4]) #Verifica o checksum do pacote if(checksum == pacote[2]): dados_arquivo = Pacote(pacote[3], pacote[4], checksum) fila_de_pacotes.append(dados_arquivo) #Insere na fila de pacotes pacotes_confirmados.append(ACK) #Insere na fila de pacotes confirmados NFE = NFE + 1 ACK = str(ACK) udp.sendto(ACK,cliente) #Selective ACK elif(flag == 'a'): if(ACK in pacotes_confirmados): #Reenvia o ACK ACK = str(ACK) udp.sendto(ACK, cliente) else: checksum = gera_md5(pacote[4]) #Checksum do pacote chegou OK if(checksum == pacote[2]): dados_arquivo = Pacote(pacote[3], pacote[4], checksum) fila_de_pacotes.append(dados_arquivo) #Insere na fila de confirmados pacotes_confirmados.append(ACK) ACK = str(ACK) udp.sendto(ACK, cliente) udp.shutdown(socket.SHUT_RDWR) udp.close()
def main(): try: global pacotes_a_enviar, tempo_de_execucao tempo_de_execucao = time.time() #Define a leitura dos argumentos de linha de comando parser = argparse.ArgumentParser(description='Cliente UDP', add_help=False) parser.add_argument('-f','--arquivo', action='store', dest='file_name') parser.add_argument('-h','--endereco', action='store', dest='address') parser.add_argument('-p','--porto', action='store', dest='port') #Conforme especificação, -w, -g e -a são mutualmente exclusivos grupo = parser.add_mutually_exclusive_group() grupo.add_argument('-w', action='store_true') grupo.add_argument('-g', action='store_true') grupo.add_argument('-a', action='store_true') #parser.add_argument('-t', '--taxa', action='store', dest='taxa') argumentos = parser.parse_args() #Se os argumentos não estiverem OK, termina a execução do programa if (verifica_argumentos(argumentos) == 1): print 'Exemplo : python -i arquivo -f arquivo_entrada -h endereco -p numero_porto \'-w ou -g ou -a i\'' print parser.parse_args() return #taxa = int(argumentos.taxa) flag = armazena_flag(argumentos) #Abre e fecha o arquivo para gerar o checksum arquivo = abre_arquivo_leitura(argumentos.file_name) buf = arquivo.read() checksum_arquivo = gera_md5(buf) fecha_arquivo(arquivo) # abre o arquivo para leitura arquivo = abre_arquivo_leitura(argumentos.file_name) # Lê o tamanho do arquivo e define o tamanho do pacote tamanho_pcte = 1460 arquivo.seek(0,os.SEEK_END) tamanho_arquivo = arquivo.tell() total_de_pacotes = int (math.ceil(tamanho_arquivo/1460)) #Conexao HOST = argumentos.address #Endereco do servidor PORT = int(argumentos.port) #Porta na qual o servidor sera acessado CLIENT = '10.0.0.2' dest = (HOST, PORT) udp = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Uma thread le os dados do arquivo e os armazena no buffer thread1 = threading.Thread(target=le_dados_arquivo,args= (arquivo, tamanho_pcte, tamanho_arquivo)) thread1.daemon = True #Termina quando a thread principal terminar thread1.start() #A outra thread envia os pacotes thread2 = threading.Thread(target=envia_pacotes,args=(udp,HOST,PORT,CLIENT,total_de_pacotes , checksum_arquivo, flag)) thread2.daemon = True #Termina quando a thread principal terminar thread2.start() while pacotes_a_enviar != 0: pass except KeyboardInterrupt: print 'Encerrando cliente.' return except Exception, IOError: traceback.print_exc(file=sys.stdout) sys.exit()