Eu estou usando o ruby 2.0.0p451 (2014-02-24) [x64-mingw32] e eu me deparei com algo que funcionou anteriormente na versão 1.9.x que não funciona aqui. Eu queria saber se eles mudaram o comportamento, ou se estou fazendo algo errado, ou se isso é um bug.
Estou enviando um byte por um soquete xFF
e eu recebo do outro lado, mas quando eu tento compará-lo a si mesmo (que deve retornar true) ele não retorna a saída esperada.
Exemplo, eu mando a string xFFx50x00usernamex00555x00
e eu recebo bem do outro lado, mas quando eu tento comparar o primeiro byte para si o condicional se comporta de forma errada.
Aqui estão alguns exemplos de código para que você possa ver como eu estou manipulando os dados (desnatado para o código relevante)
class PacketReceiver
def setpacket( buffer ); @buffer = buffer; end
def getbyte
byte = @buffer[0..0]
@buffer = @buffer[1..-1]
byte
end
end
def parsepacket(packet)
#@receiver = PacketReceiver.new #defined elsewhere in code
@receiver.setpacket packet
return false unless @reciever.getbyte.eql? "xFF" #the bugged line
#Everything works beyond this point
packet_id = @reciever.getbyte
case packet_id
when "x50"
return sid_requesting_config
when "x51"
sid_requesting_data_response
when "x52"
sid_keep_alive_response
else
puts "failed"
return false
end
return true
end
Na versão 1.9.X unless
declaração estava funcionando bem. Ao depurar os dados, os dados retornados de @receiver.getbyte
é de fato "xFF", mas por algum motivo o eql?
a comparação está retornando false em vez de true fazendo com que a função retorne false. Se eu remover este byte da mensagem e remover a verificação, o resto do código também chama o getbyte
método funciona bem.
Além disso, se eu alterar o byte para "x55" em vez de "xFF", o condicional unless
instrução funciona como deveria.
Eu não sei o que está acontecendo. O xFF é reservado para algo?
Respostas:
0 para resposta № 1Eu estou supondo que buffer
é binário codificado (ou seja, buffer.encoding
é ASCII-8BIT). Isso significa que isso está acontecendo:
c = @receiver.getbyte # c also has binary encoding
ff = "xff" # ff is probably utf-8
c.eql? ff # comparing strings in different encodings gives you `false`
Em vez disso, você deve fazer comparações numéricas simples:
@receiver.getbyte.getbyte(0) == 255
Ou melhor ainda, modifique getbyte
para retornar um inteiro.
Eu acho que sua versão 1.9.X estava funcionando principalmente por acidente, você deveria estar usando uma simples comparação numérica o tempo todo.
Tenha em mente que você tem bytes em seu buffer (como 0xFF e 0x00) que não são válidos em strings utf-8, então você deve manter seu buffer em binário. Você pode usar force_encoding
em fatias do buffer para as partes que são utf-8 strings. Você pode querer olhar para String#unpack
também.
Note que estou ligando para os documentos específicos do Ruby 2.0.0 para combinar com a versão do Ruby que você está usando atualmente.