ruby-on-rails - Ruby Gem 随机返回编码错误

标签 ruby-on-rails ruby gem

所以我在 GitHub 上 fork 了这个 gem,认为我可以修复和更新它的一些问题以便在 Rails 项目中使用。我基本上得到了这个输出:

irb(main):020:0> query = Query::simpleQuery('xx.xxx.xxx.xx', 25565)
=> [false, #<Encoding::CompatibilityError: incompatible character encodings: UTF-8 and ASCII-8BIT>]

irb(main):021:0> query = Query::simpleQuery('xx.xxx.xxx.xx', 25565)
=> {:motd=>"Craftnet", :gametype=>"SMP", :map=>"world", :numplayers=>"0", :maxplayers=>"48"}

第一个响应是编码错误的示例,第二个是想要的输出(IP 的取出)。基本上这是在 Minecraft 服务器上查询有关它的信息。

我试过用

Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

但这只是给出了相同的响应,随机吐出编码错误而不是。

这是包含所有代码的相关 GitHub 存储库:RubyMinecraft

如有任何帮助,我们将不胜感激。

最佳答案

Query 类中有 this line :

@key = Array(key).pack('N')

这将创建一个带有关联编码 ASCII-8BIT 的字符串(即它是一个二进制字符串)。

稍后 @key 被用于 this line :

query = @sock.send("\xFE\xFD\x00\x01\x02\x03\x04" + @key, 0)

在 Ruby 2.0 中,字符串文字的默认编码是 UTF-8,因此这是将 UTF-8 字符串与二进制字符串组合在一起。

当 Ruby 尝试这样做时,它首先检查二进制字符串是否只包含 7 位值(即所有字节都小于或等于 127,最高字节为 0),如果是,它会考虑它与 UTF-8 兼容,因此可以毫无问题地将它们结合起来。如果不是,(即,如果它包含大于 127 的字节)那么这两个字符串不兼容,并引发 Encoding::CompatibilityError

是否引发错误取决于 @key 的内容,它是从服务器的响应中初始化的。有时这个值恰好只包含 7 位值,因此不会引发错误,有时会有一个字节设置了高位,因此会产生错误。这就是为什么错误看起来是“随机的”。

要修复它,您可以指定将两个字符串组合的行中的字符串文字视为二进制。最简单的方法是使用 force_encoding像这样:

query = @sock.send("\xFE\xFD\x00\x01\x02\x03\x04".force_encoding(Encoding::ASCII_8BIT) + @key, 0)

关于ruby-on-rails - Ruby Gem 随机返回编码错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17627269/

相关文章:

ruby-on-rails - 设计。无法验证 CSRF token 的真实性

ruby - 如何确保 BBEdit 运行 rvm Ruby

ruby-on-rails - 如果我只需要一个数据库和一个 API,那么使用 Sinatra 而不是 RoR 有什么好处

ruby-on-rails - 在 jruby 上安装 gem

ruby-on-rails - 回形针 gem - "Image has contents that are not what they are reported to be"错误

javascript - 我怎样才能让 Rails 不将转义引号呈现为\"

ruby-on-rails - 嵌套资源 - 如何避免冗余路由?

rubygems - 为 capybara-webkit 构建 native 扩展时出错

ruby-on-rails - rails : Custom validations using ActiveModel

ruby-on-rails - Ruby on Rails : undefined method 'new_token' for User