quarta-feira, março 18, 2009

Aperfeiçoamentos do Protocolo XModem

No post anterior, vimos o XModem "básico". Este protocolo possui algumas limitações:
  • Não prevê como interromper uma transmissão
  • Utiliza caracteres simples (e portanto frágeis) para sinalizações
  • Possui um overhead alto (4 bytes de overhead para 128 bytes de dados)
  • Utiliza uma detecção de erros frágil (checksum)
  • Não informa o tamanho do arquivo
  • Não permite retomar uma transferência interrompida
Veremos aqui alguns aperfeiçoamentos que resolvem algumas destas limitações.

Interrupção da Transmissão

Uma convenção frequente é usar o caracter CAN (0x18) para solicitar a interrupção da transmissão. Quando suportado, o CAN é aceito pelo transmissor no lugar de ACK e NAK e no receptor no lugar de um pacote.

O suporte ao CAN agrava o próximo problema, o uso de caracteres isolados.

Uso de Caracteres Isolados

Idealmente, um protocolo deveria utilizar sempre pacotes para garantir que apenas comunicações validas são interpretadas. O XModem utiliza os seguintes caracteres isolados:
  • ACK: um ACK que for perdido ou danificado causará uma retransmissão, o que é perfeitamente aceitável. Se um ACK espúrio for recebido pelo transmissor isto causará uma dessincronização do número dos pacotes e consequente interrupção da transferência.
  • NAK: se um NAK for perdido ou danificado causará um timeout (salvo se for convertido em ACK). Um NAK espúrio recebido pelo transmissor causará uma retransmissão. Ambos os casos são perfeitamente aceitáveis.
  • EOT: se o EOT for perdido ou danificado ocorrerá uma retransmissão. Entretanto se um ACK espúrio for recebido pelo receptor ele considerará a transmissão encerrada com sucesso, o que é problemático. Para evitar isto, algumas implementações respondem com NAK ao primeiro EOT recebido e aguardam a sua retransmissão para confirmar o fim da transferência.
  • CAN (se usado): se um CAN for perdido ou danificado, a solicitação de interrupção não será bem sucedida. Se um CAN espúrio for recebido, a transferência será interrompida. Embora estas duas situações não sejam críticas elas são desagradáveis. Uma solução é enviar uma sequência de CANs e só interromper ao receber dois (ou mais) CANs consecutivos.
Overhead e XModem-1K

O pacote do XModem possui 132 bytes, dos quais 128 são de dados. Para reduzir o overhead existe o XModem-1K, que possui 1024 bytes de dados nos pacotes. Para distinguir os pacotes com 1024 bytes dos com 128, o byte inicial é substituído de SOH (0x01) para STX (0x02). O resto do protocolo é idêntico.

O receptor do XModem-1K deve estar preparado para receber pacotes dos dois tipos. Isto permite que o transmissor otimize o final da transferência, selecionando o tamanho mais apropriado para a quantidade de bytes a enviar.

XModem-CRC

O checksum usando no XModem é frágil. Intuitivamente, temos somente 256 valores possíveis para o checksum o que propicia acertar o checksum "por acaso".

O XModem-CRC substitui o checksum por um CRC de 16 bits, aumentando o tamanho do pacote de um byte. Explicar o funcionamento do CRC é uma tarefa longa (inclusive assunto de livros), porém basta considerar que não somente estamos falando de 65536 valores possíveis mas que o algorítmo garante a detecção de todos os erros de um ou dois bits no pacote.

O CRC utilizado é o chamado CRC CCITT, baseado no polinômio X^16 + X^12 + X^5 + 1. No pacote do XModem o CRC é transmitido com o byte mais significativo primeiro. Existem várias formas de calcular o CRC, há anos utilizo um método que dispensa o deslocamento bit-a-bit e o uso de tabelas, descrito no artigo The Great CRC Mystery de Terry Ritter, publicado na revista Dr Dobb's de Fevereiro de 1986.

O uso de CRC é uma iniciativa do receptor. Para isto ele transmite inicialmente o caracter 'C' ao invés de NAK. Para compatibilidade com o XModem Checksum, após algumas tentativas o receptor deve transmitir NAKs e utilizar checksum.

O uso de pacotes de 1K e do CRC são independentes. Entretanto, por motivos de confiabilidade não é recomendado usar pacotes de 1K com checksum.

O Tamanho do Arquivo

Uma vez que o XModem não informa o tamanho do arquivo e utiliza pacotes de tamanho fixo, o arquivo recebido tem sempre tamanho múltiplo de 128 bytes. Isto vem de uma característica do sistema CP/M-80 (onde o XModem foi inicialmente implementado).

Para resolver esta limitação e acrescentar algumas facilidades adicionais, foi criado o protocolo YModem, que é uma evolução direta do XModem e veremos no próximo post.

Retomada de Transferências.

Caso uma transferência XModem (ou YModem) seja interrompida, ela tem que ser recomeçada do seu início. Isto criava uma certa tensão ao ultrapassar a marca dos 70% na transferência de arquivos grandes (tensão esta que sobrevive nos tempos da internet devido ao não suporte universal para a retomada no protocolo FTP).

Isto viria a ser corrigido em outros protocolos, notadamente no ZModem. Entretanto, apesar do nome, o ZModem tem pouca semelhança com o XModem e é bastante complexo e provavelmente não vou abordá-lo nesta série de posts.

Referência

XMODEM/YMODEM PROTOCOL REFERENCE
- Edited by Chuck Forsberg

3 comentários:

Charles Oliveira disse...

Daniel, seu blog é fantástico, li quase todos os topicos sobre protocolo XModem e deriacoes...
Estou desenvolvendo um sofware que utiliza o protocolo Xmodem e o E1381 da ASTM. Estou com dificuldades de implentar este ultimo, será que vc poderia me ajudar? caso sim posso enviar modelos deste protocolo....

Desde já agradeço

Charles Oliveira
msn/email: charles.so@hotmail.com

Daniel Quadros disse...

Charles,

Para variar estou meio atrapalhado e portanto vai ser difícil achar tempo para estudar este protocolo. De qualquer forma, você pode enviar a documentação para o email que está no Quem Sou Eu / Contato.

[]

Charles Oliveira disse...

Daniel,

Muito obrigado pelo retorno, estarei encaminhado ao seu email um arquivo de texto com as especificações do protocolo.