Искаженное шестнадцатеричное сообщение через сокет
Вопрос
Я пытаюсь передать шестнадцатеричное сообщение с сервера C Java-клиенту. Связь работает.Но к шестнадцатеричному значению, которое я получаю на Java-клиенте, кажется, добавлен «ff».Почему это происходит?
На стороне C, когда я печатаю байты, которые хочу отправить (в шестнадцатеричном формате), они кажутся нормальными.
См. приведенный ниже код:
Сервер C:
родовое словоКлиент Java:
родовое словоВыход: значение len= -36 буфер [5]= 0 буфер [6]= 0xfffffffdc
ОБНОВЛЕНО
Вот мой вывод wirehark (это то, что сервер C отправляет клиенту Java):
Обратите внимание, что в строке 5 «00 dc» соответствует datalen= 220, который должен храниться как таковой в len на клиенте Java.Итак, в Java-клиенте явно есть какая-то ошибка.Как вы все упомянули, я могу использовать Integer.toHexString (((int) buffer [index]) & 0xFF) для печати.Но мне нужно сохранить массив байтов с правильными шестнадцатеричными значениями.Пожалуйста, помогите
родовое словоРешение
Вашим первым шагом в этой ситуации должно быть наблюдение, что передается "по сети". Если можете, рассмотрите возможность использования wirehark или tcpdump , чтобы увидеть, что передается. Таким образом вы сможете выяснить, что работает не так, как ожидалось. Оба могут отслеживать сокеты, привязанные к локальным IP-адресам, а также сокеты обратной петли.
Но, судя по всему, я согласен с тем, что происходит столкновение подписанный / неподписанный.
Если у вас есть этот вывод, он поможет определить, "кто" виноват.
< sizesUpdate:
Как уже упоминалось, вы захотите замаскировать и использовать только самые младшие 8 бит, и это можно сделать следующим образом:
родовое словоВы можете ввести это в свой код двумя способами, один - с помощью простой статической функции, которую вы вызываете для каждого байта, например
родовое словоДругой - функция-оболочка для DataInputStream.read (), которая считывает байты в буфер, а затем маскирует их все. Это может выглядеть примерно так:
родовое словоЕсли вы выбрали первый способ, вы бы захотели вызвать mask () для любого используемого значения buffer []. Итак
родовое словобудет
родовое словоЕсли вы выбрали второй способ, вы бы изменили буфер с массива типа byte на int:
родовое словои может обновить ваш цикл while примерно так:
родовое словоНо при этом ...
Лучше, чем любой из этих вариантов, использовать метод DataInputStream readUnsignedByte .
Вам нужно будет вытащить из потока 40 байтов за раз, но это будет гораздо более понятно, чем вы занимаетесь, чем тидлинг. На мой взгляд, это был бы предпочтительный подход.
Другие советы
Байты в java подписаны.Таким образом, каждое значение, у которого установлен самый старший бит, является отрицательным значением.Когда он преобразуется в целое число, что происходит при вызове Integer.toHexString, знак расширяется.Таким образом, если это было 10000000b, это будет 11111111111111111111111110000000b или 0xFFFFFF80 вместо 0x80.Потому что это то же отрицательное значение в 32 бита.Делаем
общийДолжен исправить.
Кстати, в java нет беззнаковых типов.
Integer.toHexString(buffer[index] & 0xFF )
устранит вашу проблему.
Похоже на распространение знаковых битов.len и другие переменные JAVA выглядят как подписанные, хотя не должны.