Twitter @HigenekoTwitter #XNA
ビットフィールドは古くから知られている素晴らしいデータパッキング手法です。C#プログラマーがビットフィールドを使う機会は非常に少ないですが、ネットワークパケットの圧縮にはもってこいなので、この機会に使ってみましょう。
バイトは8ビット、intは32ビット。でも、送るべきデータが8ビットや32ビットの倍数にならないときはどうします?例えば以下のようなデータを送るとします。
bool isAlive; // 生きているか? bool isFiring; // 撃っているか? enum Species // 種類 { Camel, // ラクダ Cat, // ねこ Caterpillar, // いもむし Cheetah, // チーター Chimpanzee, // チンパンジー Cobra, // コブラ Cormorant, // 鵜(う) Cougar, // クーガー Coyote, // コヨーテ Crab, // カニ Crocodile, // ワニ } packetWriter.Write(isAlive); packetWriter.Write(isFiring); packetWriter.Write((byte)species)
これで3バイトになりますが、実際にはそんなにいりません。ブーリアン型は1ビットしか必要としませんし、生物の種類も11種しか居ないので4ビットで足ります。
それぞれのフィールドにどれだけのビット数が必要かが判れば、ビットシフトすることによって複数のビット群を1つbyteやintにまとめることができます。使いやすいように、指定されたビット群をbyteやintといった値にまとめるメソッドを作るといいでしょう。
ここでは、先の例では3バイトを送っていたところを1バイトにまとめて送ることができます(まだ2ビット余ってる)
void AddToBitfield( ref int bitfield, int bitCount, int value ) { bitfield <<= bitCount; bitfield |= value; } int bitfield = 0; AddToBitfield( ref bitfield, 1, isAlive? 1: 0 ); AddToBitfield( ref bitfield, 1, isFiring? 1: 0 ); AddToBitfield( ref bitfield, 4, (int)species ); packetWriter.Write((byte)bitfield);
AddToBitfieldメソッドは2つのことをします
読み込むためには、逆のプロセスを行います。
int ReadFromBitfield( ref int bitfield, int bitCount ) { int value = bitfield & ((1 << bitCount) - 1 ); bitfield >>= bitCount; return value; } int bitfield = PacketReader.ReadByte(); species = (Species)ReadFromBitfield( ref bitfield, 4 ); isFiring = ReadFromBitfield( ref bitfield, 1 ) != 0; isAlive = ReadFromBitfield( ref bitfield, 1 ) != 0;
書き込んだ順番とは逆に読み込んでいることに注意してください。
ReadFromBtfieldメソッドはAddToBitfieldと逆のことをします。
ビットフィールドはenumやブーリアンをまとめるのに有効ですが、他の数値データも前回紹介した量子化の手法と組み合わせることで格納することができます。
原文:http://blogs.msdn.com/shawnhar/archive/2007/12/28/network-compression-bitfields.aspx
PingBack from http://www.biosensorab.org/2008/02/07/%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e3%80%80%e3%81%9d%e3%81%ae%ef%bc%97%e3%80%80%e3%83%93%e3%83%83%e3%83%88%e3%83%95%e3%82%a3%e3%83%bc%e3%83%ab%e3%83%89%e3%81%a7%e5%9c%a7%e7%b8%ae/
プログラム中にtypoがあります。
ReadFromBitfireld