web-dev-qa-db-ja.com

ネットワークでバイトオーダーを安全に無視できますか?

クライアントをWindowsで実行し、サーバーをLinuxで実行するサーバークライアントアプリケーションを開発しています。後でクライアントをMacとLinuxに移植するかもしれませんが、まだ移植していません。

最近のすべてのホームコンピューターはリトルエンディアンで実行されます。しばらくググってみましたが、ビッグエンディアンで動作するデバイスのリストが本当に見つかりませんでした。私の知る限り、一部のMotorolaチップは依然としてビッグエンディアンを使用しており、おそらく一部の電話を使用しています(アプリをスマートフォンに移植する予定はないので、これは私には関係ありません)。それで、reading and writingのために、すべての整数、short、float、doubleなどのバイトを再配置するのはなぜですか?すでにknowサーバーとクライアントの両方がリトルエンディアンで実行されていますか?

それは、不必要な作業です。ですから、私の質問は、エンディアンを無視してリトルエンディアンのデータを安全に送信することはできますか?欠点は何ですか?

23
tkausl

...なぜバイトを再配置するのですか...サーバーとクライアントの両方がリトルエンディアンで実行されていることをすでに知っているのに、どうしてですか?それは、行う必要のない不必要な作業です。

コードが常にリトルエンディアンアーキテクチャで実行されることが保証できる場合にのみ必要です。長い寿命を持つことを意図している場合、ビッグエンディアンアーキテクチャが「イン」になり、それがあなたの申請。

ネットワーク標準のバイト順序があります。これはビッグエンディアンですが、プロトコルを設計するときにそれに従う必要があるということは何もありません。コードを実行しているシステムの大部分がリトルエンディアンであり、パフォーマンスが重要であることが事前にわかっている場合は、「tkausl標準バイト順」であることを宣言し、それに従ってください。通常はhtons()を呼び出して必要な順序に並べますが、リトルエンディアンアーキテクチャでは条件付きで何もコンパイルせず、再配置を行うhtots()というマクロを記述します。ビッグエンディアン。

インバウンドとアウトバウンドの変換を行うコードを維持することは、それほど大きな努力ではありません。メッセージが非常に多い場合は、メッセージを表現する方法を見つけ、インバウンドとアウトバウンドの変換を生成するプログラムを作成します。

29
Blrfl

それはあなたのプロトコルです。

安全に無視することはできません。しかし、安全にラベルを付けることができます。クライアントとサーバーを制御します。プロトコルを制御します。双方が同意するかどうかを知っている限り、ビッグエンディアンかリトルエンディアンかを気にしないのは意味がありませんか?

これはオーバーヘッドを意味します。次に、なんとかしてエンディアンをマークする必要があります。それをすれば、私は何でもそれを読むことができます。

データのオーバーヘッドが不要で、CPUが退屈して何かを探している場合は、conformを使用します。

7
candied_orange

したがって、私の質問は、エンディアンを無視してリトルエンディアンのデータを安全に送信できるかどうかです。

これには2つの解釈があります。

  • アプリケーション/プロトコルを常に設計する場合1 リトルエンディアンを送信すると、エンディアンを無視できなくなります。

  • ネイティブエンディアンが何であれ送受信するようにアプリケーション/プロトコルを設計する場合、同じネイティブエンディアンを持つプラットフォームでアプリケーションを実行する限り、それらは機能します。

    それは「安全」ですか2?それはあなたが判断することです!しかし、確かにリトルエンディアン、ビッグエンディアン、または...エンディアンを使用する一般的なハードウェアプラットフォームがあります。

    参照:

欠点は何ですか?

エンディアンを無視することの明らかな欠点は、ネイティブエンディアンが異なるプラットフォーム間でアプリケーションやプロトコルを実行する必要がある場合、問題が発生することです。アプリケーションが壊れるので、問題を修正するにはアプリケーションを変更する必要があります。また、バージョンの互換性の問題などにも対処してください。

明らかに、ほとんどの現在の世代のプラットフォームは、ネイティブリトルエンディアンですが、1)一部はそうではなく、2)将来何が起こるかを推測できるだけです。


1-常に...ネイティブビッグエンディアンのプラットフォームを含みます。

2-実際、「安全」とはどういう意味ですか?ハードウェアプラットフォームの将来の方向性を予測するように依頼されている場合...客観的に回答することはできません。

6
Stephen C

Cの標準BSDネットワークスタックにはhton/ntoh機能(network-to-Host/Host-to-network)は、ネットワークネイティブマシン(ビッグエンディアン)でno-opsに展開されます。ネットワークネイティブのバイトオーダーがリトルエンディアンであるシナリオでは、これらに対応する独自のものが必要になります。

それはそれを行うための堅牢な方法です。

それは型にはまらないでしょうが、私はそれで何も悪いとは思いません。ネットワーク化されたコンピューターは常にバイトストリームを取得し、それらのバイトを解釈する方法についてプロトコルについて合意する必要があります。これはほんの一部です。

3
PSkocik

エンディアンネスだけが考慮事項ではありません。整数のサイズ、送信または受信する可能性のある構造体のパッキングなどがあります。

これはすべて無視できます。誰もあなたを強制することはできません。一方、安全で信頼できる方法は、外部フォーマットを文書化してから、プロセッサ、プログラミング言語、プログラミング言語の実装に関係なく、外部フォーマットを正しく読み書きするコードを作成することです。

通常、コードは多くありません。しかし、これには大きな利点があります。コードを読んでいる人は、自分が無知だと疑ったり、外部データの交換について何も知らなかったり、一般に信頼できないコードを書いたりしません。

3
gnasher729

サーバー間でデータを送信するために使用されるさまざまなプロトコルは、リトルエンディアン番号を使用します。

  1. BSON
  2. プロトコルバッファ
  3. Capn Proto

リトルエンディアン番号を持つものとビッグエンディアン番号を持つもののさまざまな形式の詳細については、 https://en.wikipedia.org/wiki/Comparison_of_data_serialization_formats を参照してください。

リトルエンディアンの数値に基づくプロトコルを使用しても、まったく問題はありません。ビッグエンディアンマシンは、リトルエンディアンマシンがビッグエンディアン番号を読み取ることができるのと同じように、リトルエンディアン番号を読み取ることができます。リトルエンディアンのマシンでビッグエンディアンの数値をデコードするための余分な計算コストを回避するために、多くの人が特別にそれを行っています。

これらの既存のプロトコルのいずれかの上にプロトコルを構築する場合は、問題を自分で心配する必要もありません。問題はすでに解決されています。ビッグエンディアンプラットフォームでコードを実行する場合、これらのプロトコルを実装するライブラリが自動的に値を正しくデコードすることを保証します。

3
Winston Ewert

ビッグエンディアンシステムの1つの例は、ルーターで使用されるMIPSです。 ARMとMIPSはどちらもエンディアンで切り替え可能ですが、ネットワークハードウェアを容易にするため、多くの場合MIPSはビッグエンディアンです(Wordの最も重要な部分は最初に受け取る部分であり、ルーティングを行うことができます)ワード全体をバッファリングする必要があるのではなく、ワードの残りを受け取る前の決定).

したがって、「Linux」が何を意味するかによって異なりますが、OpenWRTを実行しているルーターのような小さなシステムでサーバーアプリを実行したい場合は、ビッグエンディアンのサポートを検討する必要があります。

いつものように、仮定を単純化することは、仮定に合わない何かにぶつかるまで、まったく賢明な最適化です。あなたがそのような問題に遭遇した場合、それらをほどくのがどれほど苦痛であるかを言うことができるのはあなただけです。

2
user1908704

答えはどれもかなり正確だとは思いません。 Wikipedia によると、エンディアンネスはワードを構成するバイトの順序です。

4バイトを取り、それらをintとして解釈しましょう。リトルエンディアンシステムでは、バイトは右から左に解釈され、ビッグエンディアンシステムでは逆に解釈されます。明らかに、どちらの目的でintを解釈するかについて合意することが重要です。

Jsonやxmlを使用している可能性のある最新のネットワークプロトコルに少しズームしてみましょう。これらの形式はいずれも、intを4バイトとして転送しません。それらは、受信側でintとして解析されるテキストとしてデータを転送します。

つまり、jsonやxmlを使用する場合、エンディアンは重要ではありません。 tcpヘッダーにはビッグエンディアンを使用する必要があるため、ネットワークバイトオーダーと呼ばれますが、ほとんどのプログラマーは日常的にそれらをいじる必要はありません。

今日最も広く使用されているエンコーディングは、utf-8であり、これは-- エンディアンに関する問題の影響を受けない にもなります。

だから私はイエスと言うでしょう。 utf-8を使用して転送されたテキストベースのフォーマットを使用する場合は、エンディアンを無視しても安全です。

0

ビッグエンディアンのシステムは間もなくリリースされるようです。従来のunixの多くはビッグエンディアンを使用していましたが、x86でのLinuxを支持して長年衰退してきました。

アームはバイエンディアンですが、ビッグエンディアンバリアントはめったに見られないようです。

mipsは両方の亜種に存在します。ビッグエンディアンバリアントは主にネットワーキングアプライアンスで見られます(歴史的な理由により、インターネットプロトコルは一般にビッグエンディアンを使用します)。

ppcは伝統的にビッグエンディアンで、一部は両方のエンディアンをサポートしていましたが、IBMは64ビットppcのリトルエンディアンモードをプッシュしているようです(最近、ppc64elポートがDebianとUbuntuにプッシュされました)。

sparcは通常ビッグエンディアンですが、ここでも減少傾向にあります。

既存のプロトコルを実装している場合は、明らかにその仕様に従う必要があります。 IETFで新しいプロトコルを祝福したい場合は、ビッグエンディアンが既存のプロトコルですでに使用されているため、ビッグエンディアンの方が簡単ですが、新しい「グリーンフィールド」プロトコル設計のIMOリトルエンディアンが最適です。

リトルエンディアンシステムでは動作しないマクロを最初から挿入するか、またはビッグエンディアンシステムに移植する必要があるまで、またはそうでない場合を気にする必要はありません。

0
Peter Green