1

UDP 経由で非常に長い 2 進整数 (200 ビット程度) を送信しようとしています。Array の pack メソッドを使用しようとすると、変換しようとしている文字列が大きすぎるというエラーが表示されます。

私はこれについて間違った方法で進んでいますか?

ruby-1.8.7-p352 :003 > [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
RangeError: bignum too big to convert into `unsigned long'
from (irb):3:in `pack'
from (irb):3

この番号は、DNS クエリ パケットを表すことになっています (これは宿題のためです。DNS ライブラリの使用は許可されていません)。

4

2 に答える 2

4

番号を小さな断片に分割する必要があります。おそらく最善の方法は、一度に 32 ビットをエンコードすることです。

> num = 0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101
=> 17502556204775004286774747314501014869
> low_1 = num & 0xFFFFFFFF
=> 2864534869
> low_2 = (num >> 32) & 0xFFFFFFFF
=> 625650362
> low_3 = (num >> 64) & 0xFFFFFFFF
=> 1297454421
> low_4 = (num >> 96) & 0xFFFFFFFF
=> 220913317
> (low_4 << 96) + (low_3 << 64) + (low_2 << 32) + low_1
=> 17502556204775004286774747314501014869
> msg = [low_4, low_3, low_2, low_1].pack("NNNN")
=> "\r*\336\245MU\225U%J\252\272\252\275UU"
> msg.unpack("NNNN").inject {|sum, elem| (sum << 32) + elem}
=> 17502556204775004286774747314501014869

32ここでビットを好むのは、これらをNetwork Byte Orderでパックするためです。これにより、他のプラットフォームとの相互運用がはるかに簡単になります。このpack()メソッドは、ネットワーク バイト オーダーの 64 ビット整数を提供しません。(POSIX は 64 ビット ルーチンを提供していないため、これはそれほど驚くべきことではありません。)

于 2011-11-20T08:24:49.270 に答える
-1

Ruby 1.9.3 は正常に動作します。

irb(main):001:0> [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
=> "UU\xBD\xAA"
于 2011-11-20T08:15:25.960 に答える