我正在尝试通过UDP发送一个非常长的二进制整数(大约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库。)
答案 0 :(得分: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位例程。)
答案 1 :(得分:-1)
Ruby 1.9.3正常工作。
irb(main):001:0> [0b1101001010101101111010100101010011010101010110010101010101010010010101001010101010101011101010101010101111010101010101010101].pack('i')
=> "UU\xBD\xAA"