Сетевое взаимодействие между сервером C # и клиентом JAVA: как с этим справиться. переход?

#java #networking #unsigned

#java #сеть #без знака

Вопрос:

У меня есть сервер C #, который нельзя изменить. В C # байт находится в диапазоне от 0 до 255, в то время как в JAVA он находится в диапазоне от -128 до 127.

Я прочитал о проблеме с неподписанными байтами / целыми числами / etc, и единственный реальный вариант, как я выяснил, — использовать «больше памяти» для представления неподписанной вещи: http://darksleep.com/player/JavaAndUnsignedTypes.html

Это действительно так?

Таким образом, при наличии сетевого взаимодействия между клиентом JAVA и сервером C # клиент JAVA получает массивы байтов с сервера. Сервер отправляет их «как неподписанные», но при получении они будут интерпретироваться как подписанные байты, верно?

Должен ли я затем вводить каждый байт в Int, а затем добавлять 127 к каждому из них?

Я здесь не уверен… но как мне интерпретировать его обратно к тем же значениям (int, strings и т.д.), Что и на сервере C #?

Я нахожу всю эту ситуацию чрезвычайно запутанной (не говоря уже о проблемах с конечностью, но это для другого поста).

Комментарии:

1. Если я не помню, что мои двойки дополняют математику совершенно неправильно, это будет от -128 до 127 в Java (не от -127 до 128), и, как указывает @JonSkeet, от 0 до 255 (не от 0 до 254) в C #.

2. Да, да, да. вы поняли идею…

3. В итоге я использовал байт-буферы JAVA: s и изменил порядок (…) для них, чтобы перевести с-и-на маленький / большой порядковый номер. Если бы я этого не сделал, это вообще не сработало. Когда дело доходит до подписи, я не мог сделать ничего другого, кроме как интерпретировать C # uint в JAVA int, и просто надеюсь, что мы не превысим 2 миллиарда…

Ответ №1:

Байт равен 0-255 в C #, а не 0-254.

Однако в большинстве случаев вам действительно не нужно беспокоиться — в основном как в C #, так и в Java байт равен 8 битам. Если вы отправите массив байтов из C #, вы получите те же биты в Java и наоборот. Если затем вы преобразуете части этого массива байтов в 32-разрядные целые числа, строки и т. Д., Все будет работать нормально. Подписанность байтов в Java почти всегда не имеет значения — это проблема, только если вы обрабатываете их численно.

Более серьезной проблемой является возможность изменения порядка байтов при (скажем) преобразовании 32-разрядного целого числа в 4 байта в Java, а затем считывании данных в C # или наоборот. Вам нужно будет предоставить больше информации о том, что вы пытаетесь сделать, чтобы мы могли вам помочь. В частности, у вас уже есть протокол, которого вам нужно придерживаться? Если это так, это в значительной степени решает, что вам нужно делать, и насколько сложно это будет зависеть от того, какой протокол.

Если вы выбираете протокол, вы можете использовать независимый от платформы формат сериализации, такой как буферы протокола, который доступен для обоих .СЕТЬ и Java.

Комментарии:

1. Спасибо. Я понимаю. Хм, я попробую еще немного с байтом. Однако, когда дело доходит до конца, я также немного думал об этом сегодня. И да, уже существует предопределенный протокол (который мы написали, но сейчас не можем изменить). Этот протокол был написан на C # и содержит много чисел без знака.

2. @Ted: Возможно, будет сложно записать их из Java, но я уверен, это не будет слишком сложно. Однако вы не сможете представлять неподписанные значения в Java как значения без знака — поэтому, если у вас есть a uint в C #, вам нужно либо сохранить его в a long в Java, либо просто учесть разницу в том, как вы используете значения.

3. На самом деле я переношу наше приложение C # / Windows Mobile на Android, поэтому сейчас я изучаю это…

Ответ №2:

К сожалению, да … ответ заключается в том, чтобы «использовать больше памяти», по крайней мере, на каком-то уровне.

Вы можете хранить данные в виде byte массива в java, но когда вам нужно использовать эти данные численно, вам нужно перейти к an int и добавить 256 к отрицательным значениям. Побитовое amp; решение сделает это за вас быстро и эффективно.

 int foo;
if (byte[3] < 0)
    foo = (byte[3] amp; 0xFF);
else
    foo = byte[3];
  

Комментарии:

1. Я этого не понимаю. Как я могу представить его как long, если я отправляю его на сервер C #, который представляет его как uint, 4 байта? C #-сервер получит 8 байт (длиной) и возьмет первые 4 байта и преобразует их в uint… что будет неправильным, я предполагаю…

2. Весь массив байтов будет испорчен, когда сервер ожидает, что 4 байта будут интерпретироваться как uint… Очень беспорядочно. Допустим, я полностью переписываю весь протокол, должен ли я вообще прекратить использование чисел без знака на стороне C #?

3. Ну, нет. У вас есть нужное количество битов на каждом конце. Единственная проблема заключается в том, как они интерпретируются. Да, это боль, но вам просто нужно будет отправить подписанный эквивалент из java, чтобы битовый шаблон был правильным при приведении к unsigned в C #. И когда вы говорите о многобайтовых и беспокоитесь о проблемах с порядком окончания, вы бы хотели преобразовать в сетевой порядок байтов. Если бы вам нужно было переделать протокол, вы бы либо отказались от двоичного кода, либо использовали существующий, который предоставляет библиотеки Java и C #, поэтому вам вообще не нужно было с ним возиться (например, буферы протокола Google).