Estou desenvolvendo um aplicativo servidor-cliente no qual o cliente será executado no Windows e o servidor provavelmente no Linux. Talvez depois eu leve o cliente para o Mac e Linux, mas ainda não.
Todos os computadores domésticos hoje em dia rodam em little-endian. Pesquisei um pouco no Google, mas não consegui encontrar realmente uma lista de dispositivos que rodam em big-endian. Até onde eu sei, alguns chips da Motorola ainda usam big endian e talvez alguns telefones (não pretendo portar o aplicativo para smartphones, então isso não importa para mim). Então, por que eu reorganizaria os bytes de todo número inteiro, todo curto, todo flutuador, duplo e assim por diante, para leitura e gravação , quando eu já sei que servidor e cliente rodam em little-endian?
Isso é apenas um trabalho desnecessário a ser feito. Então, minha pergunta é: Posso ignorar com segurança o endianness e apenas enviar dados little-endian? Quais são as desvantagens?
fonte
Respostas:
Só é desnecessário se você puder garantir que seu código sempre será executado em arquiteturas little-endian. Se você pretende ter uma vida longa, vale a pena o esforço extra para evitar perturbar o código comprovado daqui a uma década, quando alguma arquitetura big endian se tornar a coisa "in" e você achar que é um bom mercado para sua aplicação.
Há uma ordem de bytes padrão de rede. É big-endian, mas nada diz que você deve cumpri-lo ao projetar seu protocolo. Se você souber antecipadamente que a maioria dos sistemas que executam seu código será pouco endian e o desempenho for crítico, declare que o "tkausl standard byte ordering" e o acompanha. Onde você normalmente chamaria
htons()
para colocar as coisas na ordem que você precisa, escreva uma macro chamadahtots()
que não compila condicionalmente em arquiteturas little-endian e faça o re-arranjo em big-endian.Manter o código para realizar as conversões de entrada e saída não é realmente um grande esforço. Se você tiver um número muito grande de mensagens, encontre uma maneira de expressá-las e escreva um programa para gerar as conversões de entrada e saída.
fonte
when designing your protocol
é importante, porque também diz implicitamente que essa opção existe apenas ao projetar um novo protocolo e não ao implementar algum protocolo existente. E mencionar a necessidade de umahtots
(e realmente uma família inteira de funções) também deixa claro que escolher uma ordem de bytes diferente não é algo que se faz para tornar o código mais simples, mas pode torná-lo um pouco mais rápido.htole32()
,htole16()
,le16toh()
, etc., bem como funções disponíveis. Infelizmente, o arquivo a ser incluído para obtê-los é ainda menos padrão:<endian.h>
ou<sys/types.h>
dependendo da plataforma.É o seu protocolo.
Você não pode ignorá-lo com segurança. Mas você pode rotulá-lo com segurança. Você controla o cliente e o servidor. Você controla o protocolo. Não faz sentido não se importar se é big endian ou little endian, desde que você saiba se os dois lados concordam?
Isso significa sobrecarga. Agora você tem que marcar seu endianness de alguma forma. Faça isso, e eu posso ler em qualquer coisa.
Se você não deseja sobrecarga de dados e sua CPU está entediada e procurando algo para fazer, faça a conformidade .
fonte
Existem duas interpretações disso:
Se você projetar seus aplicativos / protocolos para sempre enviar 1 little-endian, NÃO estará ignorando a endianess.
Se você projetar seus aplicativos / protocolos para enviar / receber qualquer endianess nativa, eles funcionarão desde que você execute seus aplicativos em plataformas com a mesma endianess nativa.
Isso é "seguro" 2 ? Isso é para você julgar! Mas certamente existem plataformas de hardware comuns que usam little-endian, big-endian ou ... bi-endian.
Referência:
A desvantagem óbvia de ignorar endianess é que, se você / seus usuários precisam executar seus aplicativos / protocolos entre plataformas com diferentes endianess nativos, você tem um problema. Os aplicativos serão interrompidos e você precisará alterá-los para corrigir o problema. E lide com problemas de compatibilidade de versões, etc.
Claramente, a maioria das plataformas de geração atual é nativamente pouco endian, mas 1) algumas não, e 2) podemos apenas adivinhar o que acontecerá no futuro.
1 - Sempre ... inclusive em plataformas nativas big-endian.
2 - De fato, o que significa "seguro"? Se você está nos pedindo para prever a direção futura das plataformas de hardware ... receio que isso não seja objetivamente responsável.
fonte
Endianness não é a única consideração. Há o tamanho de números inteiros, há pacotes de estruturas que você pode enviar ou receber, e assim por diante.
Você pode ignorar tudo isso. Ninguém pode forçar você. Por outro lado, a maneira segura e confiável é documentar um formato externo e, em seguida, escrever um código que leia ou grave o formato externo corretamente, independentemente do seu processador, linguagem de programação e implementação da linguagem de programação.
Normalmente, não há muito código. Mas tem um grande benefício: as pessoas que lêem seu código não suspeitam que você não tem noção, não sabem nada sobre troca de dados externos e escrevem código que geralmente não é confiável.
fonte
A pilha padrão BSD rede em C tem a
hton
/ntoh
funcionalidade (network-to-host
/host-to-network
) que expanda para não-ops em máquinas de rede-nativa (grande endian). Você precisaria de suas próprias contrapartes para elas no cenário em que a ordem de bytes nativos da rede é pouco endian.Essa é a maneira robusta de fazer isso.
Seria não convencional, mas não vejo nada de errado nisso. Os computadores em rede sempre recebem bytestreams e precisam concordar com os protocolos sobre como interpretar esses bytes. Isso é apenas parte disso.
fonte
Vários protocolos usados para transmitir dados entre servidores usam pequenos números endian:
Veja https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats , para obter detalhes sobre vários formatos, alguns dos quais com números little-endian e alguns com números big-endian.
Não há absolutamente nada de errado em usar um protocolo baseado em pequenos números endian. Uma grande máquina endian é tão capaz de ler pequenos números endian quanto uma pequena máquina endian pode ler grandes números endian. Muitas pessoas fizeram isso especificamente para evitar o custo extra de computação da decodificação de números big-endian em pequenas máquinas endian.
Se você constrói seu protocolo sobre um desses protocolos existentes, nem precisa se preocupar com o problema, pois ele já está resolvido. Quando você decide executar seu código em uma plataforma big endian, as bibliotecas que implementam esses protocolos cuidam automaticamente para garantir que você decodifique os valores corretamente.
fonte
Um exemplo de um sistema big endian é o MIPS usado em roteadores. O ARM e o MIPS são selecionáveis pelo endian, mas geralmente o MIPS é o big endian porque facilita o hardware de rede (a parte mais significativa de uma palavra é a parte que você recebe primeiro e pode tomar uma decisão de roteamento antes de receber o restante a palavra, em vez de precisar armazenar a palavra inteira).
Portanto, depende do que você quer dizer com 'Linux', mas se você quiser executar seu aplicativo de servidor em um sistema menor, como um roteador executando o OpenWRT, talvez seja necessário considerar o grande apoio endian.
Como sempre, fazer suposições simplificadoras é uma otimização perfeitamente sensata até o momento em que você atinge algo que não se encaixa nas suposições. Só você pode dizer o quão doloroso seria desenrolá-los se você se deparar com esse problema.
fonte
Não acho que nenhuma das respostas seja suficientemente precisa. De acordo com a Wikipedia, endianness é a ordem dos bytes que compõem uma palavra.
Vamos pegar 4 bytes e interpretá-los como um int. Em um sistema um pouco endiano, os bytes serão interpretados da direita para a esquerda e vice-verca em um grande sistema endiano. Obviamente, é importante concordar sobre qual extremidade interpretar um int.
Permite reduzir um pouco os protocolos de rede modernos que podem estar usando json ou xml. Nenhum desses formatos transferirá um int como 4 bytes. Eles transferirão os dados como texto, que serão analisados como int no lado receptor.
Portanto, no final, o endianness não importa ao usar json ou xml. Ainda precisamos usar o big endian para cabeçalhos tcp, motivo pelo qual é chamado de ordem de bytes da rede, mas a maioria dos programadores não precisa mexer com eles diariamente.
A codificação mais usada hoje em dia é o utf-8, que também parece ser imune a problemas relacionados à continuidade .
Então eu diria que sim. É seguro ignorar endianness ao usar formatos baseados em texto transferidos usando utf-8.
fonte
Os sistemas big endian parecem estar saindo. Muitos dos unixes tradicionais usavam big endian, mas estão em declínio há anos a favor do linux no x86.
arm é bi-endian, mas a variante big endian parece raramente ser vista.
mips existe em ambas as variantes. A ameaça da variante big endian é vista principalmente em aplicativos de rede (por razões históricas, os protocolos da Internet geralmente usam big endian).
O ppc era tradicionalmente big endian, com algumas partes suportando ambos, mas a IBM parece agora estar pressionando o modo little endian para o ppc de 64 bits (eles recentemente lançaram portas ppc64el no Debian e Ubuntu).
O sparc é normalmente big endian, mas novamente parece estar em declínio.
Se você estiver implementando um protocolo existente, obviamente precisará seguir as especificações. Se você deseja que a IETF abençoe seu novo protocolo, é provável que o big endian seja mais fácil, porque é isso que eles já usam em seus protocolos existentes, mas a IMO para um novo design "greenfield" de protocold é o caminho a seguir.
Você pode inserir macros desde o início, que não serão utilizadas em sistemas little endian ou não poderá se preocupar até / a menos que precise portar para um sistema big endian.
fonte