Искаженное шестнадцатеричное сообщение через сокет

StackOverflow https://stackoverflow.com/questions/5898391

  •  29-10-2019
  •  | 
  •  

Вопрос

Я пытаюсь передать шестнадцатеричное сообщение с сервера 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 выглядят как подписанные, хотя не должны.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top