Projecto de Software "Cliente/Servidor" Transferência de Ficheiros {MyFTP.doc} Um serviço de Transferência-de-Ficheiros com recuperação após falha (crash) encontra-se definido do seguinte modo: Qualquer utilizador que o deseje pode instalar no seu computador um Servidor de transferências de ficheiros, com o registo das que estão em curso. A partir de um outro qualquer computador, dito Cliente, pode ser desencadeada uma transferência de ficheiros para/de esse Servidor. Um eventual interessado numa transferência de ficheiros deve fazer o seguinte: lançar um programa, seja "MyFTP Servidor", em que o argumento Servidor remete para um hostname e porto, por ex.: MyFTP [email protected] 20000 Subsequentemente, MyFTP aceita os seguintes comandos: Put LocalPathName RemotePathName Get LocalPathName RemotePathName Status Quit Com Put, o interessado requere a Transferência de um ficheiro, no sentido Cliente ∏ Servidor; com Get, ele requere a Transferência de um ficheiro no sentido oposto, Servidor ∏ Cliente. Com Status, requere o estado da(s) transferência(s) em curso. Com Quit, requere a terminação normal de MyFTP. Os PathName fonte remetem para ficheiros eventualmente grandes (vários megabytes) e binários (por ex., .zip, .gif, .bmp, .pdf, .exe); mas também podem estar vazios. Consoante o caso, os comandos Put e Get (e bem assim os restantes) podem ou não devolver mensagens de erro; entre as possíveis, poderão citar-se as seguintes: Parâmetros insuficientes; Parâmetros em excesso; Parâmetros inválidos: PathName inválido, etc. Número máximo de Transferências em simultâneo já foi atingido Ficheiro fonte < PathName > inexistente ou inacessível Ficheiro destino < PathName > existente; pretende prosseguir com a transferência? Dificuldades na comunicação Erro de sistema Ficheiro fonte < PathName > ainda em vias de produção. Os comandos Put e Get não são bloqueantes, isto é: após invocado um deles, o MyFTP deve ficar de imediato pronto para qualquer outro comando, nomeadamente Put e/ou Get. Pelo que poderão em cada momento estar em curso de transferência vários ficheiros em simultâneo, em ambas as direcções: Cliente ∏ Servidor e Servidor ∏ Cliente. O número máximo de Transferências em simultâneo é de NMax para cada direcção. Quando um emissor já se encontra enviando um ficheiro, uma solicitação no sentido de ele começar a enviar um outro ficheiro volve-se no seguinte procedimento: ele averigua qual o número de bytes do novo ficheiro, e quantos faltam ainda enviar daquele outro ficheiro em vias de transmissão; se e só se este último fôr maior, suspende a sua transmissão, e desencadeia o envio do novo ficheiro; quando acabar esta, retoma a transmissão daquele outro ficheiro. A transferência dos ficheiros é suportada em TCP. O número de conexões-TCP simultâneas entre um Cliente e o Servidor é, no máximo, de uma. Ela é criada aquando da primeira invocação de Put ou Get. Subsequentes Put ou Get são veiculados sobre a mesma conexão-TCP. Ela é terminada quando, sobre ela, não estiver em curso nenhuma transferência (Todavia, cfr considerandos adiante sobre a retoma de transferências interrmpidas por crash). Se, após isso, fôr invocado novo comando Put e/ou Get, é re-estabelecida uma nova conexão-TCP. A terminação com sucesso de uma transferência (isto é, após o receptor ter assinalado explicitamente a recepção do último byte do ficheiro) é sinalizada no ecran do Cliente. O comando Quit somente é levado por diante se todas as transferências solicitadas tiverem entretanto findado. Se não fôr o caso, o MyFTP deverá assinalar Aguarde: transferência em curso… e, por cada ficheiro cuja transferência foi solicitada mas ainda não terminada, assinalar: Ficheiro fonte < PathName >: falta transmitir NNNNN bytes. O utilizador poderá ou não re-invocar Quit. Qualquer comando Put, Get ou Quit é ignorado após o primeiro Quit. O MyFTP parará por si quando não restar mais nenhuma transferência. Um utilizador pode, em qualquer momento, abortar MyFTP pelo simples expediente de fazer Ctrl-C seguido de 0 ou 1; as consequências são distintas, cfr. adiante. À invocação de Status, o MyFTP assinala, por cada ficheiro cuja transferência foi solicitada mas ainda não terminada: Ficheiro fonte < PathName >: falta transmitir NNNNN bytes. Durante a transferência de um ficheiro, qualquer das partes (Cliente e/ou Servidor) pode falhar. Logo que seja reposto o funcionamento normal, deverá(ão) ser retomada(s) a(s) transferência(s) dos ficheiros que eventualmente tenham sido interrompidas com tal falha. Para maior eficiência, não se recomeça do princípio: procura-se retransmitir "apenas" o que ainda não foi recebido. Para o efeito, recorre-se a pontos de sincronismo (check-points), da seguinte maneira: - a fonte de um ficheiro considera-o dividido, a partir do primeiro byte, em "páginas" consecutivas de NP bytes, numeradas 1, 2, 3, etc. - por cada "página" já enviada, a fonte envia de imediato uma mensagem especial, de pedido de sincronismo, veiculando o número cp (1, 2, 3,…) dessa página; na sua recepção, o destinatário regista de uma forma não volátil: 1) a parte do ficheiro que já foi recebida e 2) esse número cp; após o que devolve uma mensagem de confirmação de sincronismo veiculando aquele número cp. Ao chegar à fonte, fica esta então segura de que já estão no destinatário os primeiros cp * N bytes do ficheiro: se vier a ocorrer crash, a fonte necessita apenas de averiguar o último ponto de sincronismo confirmado, que remete para a última página cuja recepção já foi confirmada, e reenviar apenas os bytes das páginas seguintes. - note-se que este procedimento não é Stop&Wait: após enviar o pedido de sincronismo, e todavia sem ter recebido ainda a correspondente confirmação de sincronismo, a fonte continua a enviar o que falta do ficheiro. A retoma da transferência é efectuada do seguinte modo: 1. se o crash foi no Servidor (com kill): - o Cliente sinaliza a situação no ecran do utilizador, e tenta, a intervalos de tempo T1, repôr a comunicação com o Servidor. Quando tiver sucesso, retoma a transferência dos ficheiros cuja transmissão ainda não se concluiu ou que nem sequer ainda começou. O utilizador pode interromper este procedimento com Ctrl-C [1]; e, mais tarde, retomá-lo, com MyFTP Servidor. 2. se o crash foi no Cliente: - se ele foi causado por CTRL-C [0], todo o historial das transferências solicitadas não concluídas é eliminado, e apagados do disco quaisquer dados a elas relativos; - se ele foi causado por CTRL-C [1], então, quando fôr executado MyFTP Servidor o MyFTP averigua de imediato se existem ficheiros cuja transmissão para/de esse Servidor foi solicitada mas não concluída; em caso afirmativo, estabelece uma conexão-TCP com o Servidor e, em caso de sucesso, retoma a transferência dos ficheiros cuja transmissão ainda não se concluiu ou que nem sequer ainda começou. Para prevenir o caso de uma falha do Cliente que demore um tempo excessivo a ser resolvida (pelo que permaneceriam registos no Servidor ocupando memória…), observa-se o seguinte: imediatamente após essa falha, este dispara um Timeout (de T0 segs) sobre todas as transferências suspensas relativas a esse Cliente. Transferências que não tenham sido retomadas após esse período de tempo são abortadas: o seu historial é eliminado, e apagados do disco quaisquer dados a elas relativos Para prevenir o caso de uma falha do Servidor que demore um tempo excessivo a ser ultrapassada pelos Clientes (pelo que permaneceriam registos no Servidor ocupando memória…), observa-se o seguinte: imediatamente após a resolução dessa falha, o Servidor dispara um Timeout (de T0 segs) sobre todas as transferências suspensas. Transferências que não tenham sido retomadas após esse período de tempo são abortadas: o seu historial é eliminado, e apagados do disco quaisquer dados a elas relativos. Note-se que estes eventos (e outros, como seja por ex. o caso de ser enviada a confirmação de um ponto de sincronismo, mas, por crash, ela não chegar ao parceiro remoto) podem levar a uma des-sincronização entre fonte e destino. Em tais casos, a retoma da transferência deve sempre ser feita a partir do último byte sobre que a fonte tem a certeza de que já está no destino. No seio de uma mesma sessão (entre a invocação de MyFTP e o subsequente Quit), o utilizador pode solicitar a transferência de um ficheiro de A para B, e, posteriormente, a transferência desse mesmo ficheiro de B para A, o MyFTP deve devolver um warning: Detectado um loop, A ∏ B ∏ A; pretende prosseguir com a transferência? A transferência somente será feita em caso afirmativo. Um mesmo ficheiro fonte pode estar em vias de transferência para dois destinos (em dois Clientes diferentes). Se um dado PathName é o destino de uma transferência, ele não pode ser, ao mesmo tempo, o destino de outra(s) transferência(s) (do mesmo ou outro(s) Cliente(s)). Desenhe o software mínimo necessário: - software do Servidor, incluindo gestão dos registos e comunicações - software dos Clientes Na sua concepção, - distinga claramente o nível de protocolo MyFTP (“Transferência de Ficheiros”) dos respectivos "utilizadores", a saber: teclado e ecran nos Clientes e sistema de ficheiros nos Clientes e no Servidor; - garanta que o Servidor continua a poder servir outros clientes, mesmo após ter sido estabelecida uma conexãoTCP com algum deles; - garanta que o Servidor continua a poder servir outros clientes, mesmo após algum deles ter sofrido um crash; - siga as Recomendações acerca do Relatório preliminar publicadas - siga as Recomendações para a escrita do código publicadas. - não complique desnecessariamente os gestores de registos e não perca tempo a "embonecar" a interface homem-máquina. - todos os parâmetros (NP, NMax, T0, T1, e outros) são lidos a partir de ficheiros de configuração. Grelha de avaliação: 4 Especificação Diagramas temporais Diagramas/Tabelas de estado Especificação das PDUs 0,5 Lançamento do MyFTP Ficheiro de configuração Validação do comando MyFTP 0,5 Interface Validação de comando Put/Get, etc . 4 Transferência de ficheiro TextFile/BinFile Comandos com servidor em baixo Ficheiro fonte inexistente Ficheiro fonte em vias de produção Check-Points; variação de NP 6 Put e Get Overwrite sobre ficheiro em vias de produção Não bloqueantes; teste de NMax Ficheiro grande+ficheiro pequeno Put e Get concorrentes; teste de loop Terminar conexão-TCP após transferência Sinalização no ecran após transferência kill, Ctrl-C [0], Ctrl-C [1] Retoma após crash do cliente Retoma após crash do servidor Retoma após "passar muito tempo" Servidor concorrente, vários clientes 1 2 Status Quit Com/sem transferências em curso Reinvocação de Put/Get, Status e Quit 2 20 Qualidade do código ← Total