Home Comunidade Eventos YouTube Networks Desafios // produtos Academy News CTI | CVE Contato

04 - Tradução de Dados

video explicativo
Video explicativoEspaco reservado para o video desta anotação — adicione video: https://youtu.be/... no frontmatter da nota.

Tradução de Dados na Camada de Apresentação

1. O Problema da Heterogeneidade

Quando dois computadores heterogêneos trocam dados, não podem simplesmente copiar bytes da memória de um para o outro. O inteiro 0x01020304 armazenado em um x86 (little-endian) aparece como 04 03 02 01 na memória; um SPARC (big-endian) veria 01 02 03 04. Se copiarmos os bytes diretamente, o receptor interpretará o valor invertido.

A tradução de dados é a função primordial da camada de Apresentação: garantir que estruturas de dados locais sejam serializadas em uma forma canônica, transmitida e reconstruída fielmente no destino, independentemente de arquitetura.

2. Tradução de Codificações de Caracteres

ASCII ↔ EBCDIC

O caso clássico de tradução envolvia mainframes IBM (EBCDIC) e sistemas Unix (ASCII). Cada caractere tem um valor diferente nas duas tabelas:

Caractere ASCII (hex) EBCDIC (hex)
A 0x41 0xC1
Z 0x5A 0xE9
0 0x30 0xF0
espaço 0x20 0x40

A tradução é feita por tabelas de lookup de 256 entradas. Hoje em dia, com mainframes suportando ASCII via gateways, esse problema é raro, mas historicamente causou incontáveis bugs de internacionalização.

Unicode e a Normalização

Unicode introduz outro problema: o mesmo caractere pode ter múltiplas representações. Exemplo: "ç" pode ser:

  • U+00E7 (forma pré-composta)
  • U+0063 U+0327 (c + combining cedilla)

A camada de apresentação deve aplicar uma forma de normalização (NFC, NFD, NFKC, NFKD) para garantir comparação consistente.

3. Endianness: Big-Endian vs Little-Endian

Definição

  • Big-endian: byte mais significativo primeiro (primeiro endereço = MSB). Exemplos: SPARC, PowerPC, MIPS, IBM z/Architecture, rede IP (network byte order).
  • Little-endian: byte menos significativo primeiro. Exemplos: x86, x86-64, ARM em modo padrão.

Exemplo Prático

Inteiro 0x12345678 (decimal 305.419.896):

Ordem Memória (endereços crescentes)
Big-endian 12 34 56 78
Little-endian 78 56 34 12

Network Byte Order

Para resolver o problema, o TCP/IP definiu big-endian como network byte order. Funções como htonl(), htons(), ntohl(), ntohs() (POSIX) convertem host → network e vice-versa. Em x86 (little-endian), htonl inverte os bytes; em SPARC (big-endian), é um no-op.

Middle-Endian (Mixed-Endian)

PDP-11 usava uma ordem híbrida (34 78 12 56) — praticamente uma curiosidade histórica hoje.

4. Serialização: Formatos Modernos

XML (eXtensible Markup Language)

Padrão W3C (1998). Estruturas tipadas em texto:

<pessoa>
  <nome>João</nome>
  <idade>30</idade>
</pessoa>
  • Prós: legível por humanos, schema opcional (XSD), namespaces.
  • Contras: verboso, parsing lento, ocupa muito espaço.
  • Uso: SOAP, configurações, documentos legados.

JSON (JavaScript Object Notation)

RFC 8259 (2017). Baseado em sintaxe JavaScript:

{"nome": "João", "idade": 30, "filhos": ["Ana", "Beto"]}
  • Prós: leve, parsing trivial, compatível com web.
  • Contras: sem tipo de dados para datas, números de precisão limitada, sem comentários.
  • Uso: REST APIs, NoSQL, configurações.

Protocol Buffers (Google)

Formato binário, com schema pré-definido em arquivo .proto:

message Pessoa {
  string nome = 1;
  int32 idade = 2;
  repeated string filhos = 3;
}
  • Prós: compacto, rápido, schema versionável, tipagem forte.
  • Contras: não é legível por humanos, exige compilação de código.
  • Uso: gRPC, microserviços internos do Google, Kafka schemas.

MessagePack

Como JSON, mas binário. Uma string "João" vira A4 4A 6F 61 6F (4 bytes, prefixo A4). Mais eficiente que JSON, legível via ferramentas.

Apache Avro

Usa schema em JSON, dados em binário compacto, com schema embutido no header. Popular em pipelines Kafka/Big Data.

Thrift (Facebook)

Similar a Protocol Buffers, com suporte a RPC nativo. Binário, tipado.

CBOR (Concise Binary Object Representation)

RFC 8949. Padrão IETF para serialização binária compatível com JSON. Usado em COAP (IoT).

5. ASN.1 em Detalhe

Estrutura TLV (Tag-Length-Value)

Toda codificação ASN.1 BER segue o formato TLV:

[Tag: 1+ bytes][Length: 1+ bytes][Value: N bytes]

Tag

Contém classe (UNIVERSAL, APPLICATION, CONTEXT, PRIVATE), forma (PRIMITIVE/CONSTRUCTED) e número da tag.

Classe Bits 7-6
UNIVERSAL 00
APPLICATION 01
CONTEXT 10
PRIVATE 11

Length

Três formas:

  • Short form: bit 7 = 0, bits 6-0 = comprimento (0-127).
  • Long form: bit 7 = 1, bits 6-0 = número de bytes seguintes que contêm o comprimento.
  • Indefinite form: 0x80 ... conteúdo ... 0x00 0x00 (apenas em BER, não em DER).

Exemplo Completo

Definir um INTEGER 127:

  • Tag: 02 (UNIVERSAL PRIMITIVE INTEGER)
  • Length: 01 (1 byte)
  • Value: 7F (127)
  • Total: 02 01 7F (3 bytes)

Para INTEGER 128, precisa de 2 bytes no value:

  • Tag: 02, Length: 02, Value: 00 80 (zero inicial para indicar positivo)
  • Total: 02 02 00 80 (4 bytes)

Comparação de Tamanhos

Formato Integer 127 String "João" (UTF-8)
JSON 3 bytes (127) 7 bytes ("João")
ASN.1 BER 3 bytes 7 bytes
ASN.1 PER 7 bits 5 bytes
Protobuf 2 bytes (varint) 6 bytes

6. Comparação de Formatários de Serialização

Formato Binário/Texto Schema Tamanho relativo Parsing
XML Texto XSD opcional 100% (referência) Lento
JSON Texto Nenhum ~60% Rápido
YAML Texto Nenhum ~50% Médio
Protocol Buffers Binário Obrigatório (.proto) ~20% Muito rápido
MessagePack Binário Nenhum ~30% Rápido
ASN.1 BER Binário Obrigatório ~35% Médio
ASN.1 PER Binário Obrigatório ~10% Rápido
CBOR Binário Opcional ~30% Rápido

7. Boas Práticas

  • Sempre defina explicitamente a codificação de caracteres (UTF-8 por padrão).
  • Nunca assuma endianness — use htonl/ntohl em C ou equivalentes.
  • Versione seus schemas (Protobuf field numbers, JSON Schema $schema).
  • Valide antes de processar — dados malformados podem causar DoS ou vulnerabilities.
  • Prefira formatos binários quando volume importa (IoT, mobile, alta frequência).
  • Prefira JSON quando humanos precisam depurar ou quando o overhead é aceitável.

8. Conclusão

A tradução de dados é o coração da camada de Apresentação. Desde as tabelas ASCII↔EBCDIC dos anos 1970 até os formatos binários modernos como Protocol Buffers e MessagePack, o problema é o mesmo: como representar fielmente dados entre sistemas heterogêneos. Endianness, codificação de caracteres e formato de serialização são decisões de arquitetura que impactam diretamente performance, interoperabilidade e manutenibilidade de qualquer sistema distribuído.