Ваши отправляющие и принимающие конечные точки в настоящее время реализованы на Java. Возможно, вы используете OutputStream
на отправляющей стороне и InputStream
на принимающей стороне. Предполагая, что мы можем доверять деталям реализации базового сокета на некоторое время, мы будем считать, что любой байт, отправленный через сокет, поступит к месту назначения точно так же.
Так что же на самом деле происходит на уровне Java при выгрузке чего-либо в OutputStream? При проверке JavaDoc для метода, пишущего байтовый массив , мы видим, что все это говорит нам о том, что байты передаются по потоку. Ничего особенного там нет. Но когда вы проверите документ для метода , взяв int в качестве аргумента , вы увидите, как подробно записывается этот int: 8 бит младших разрядов передаются по потоку в виде байта, в то время как старшие 24 бита (int имеет 32-битное представление в Java) просто игнорируются.
На приемную сторону. У вас есть InputStream. Если вы не используете один из методов, считывающих непосредственно в байтовый массив , вы получите int. Как говорит документ , int будет иметь значение от 0 до 255 включительно или -1, если достигнут конец потока. Это важный бит. С одной стороны, мы хотим, чтобы все возможные битовые комбинации одного байта были читаемыми из InputStream. Но у нас также должен быть какой-то способ обнаружения, когда чтение больше не может возвращать значимые значения. Вот почему этот метод возвращает int вместо байта ... Значение -1 - это флаг, указывающий, что конец потока достигнут. Если вы получаете что-то кроме -1, единственное, что вас интересует, это младшие 8 бит. Поскольку это может быть любая битовая комбинация, их десятичное значение будет в диапазоне от -128 до 127 включительно. Когда вы читаете непосредственно в байтовый массив вместо int per int, это «обрезание» будет сделано для вас. Так что есть смысл, что вы увидите эти негативные ценности. Тем не менее, они только отрицательны из-за того, как Java представляет байт в виде десятичного числа со знаком. Единственная вещь, которая представляет интерес, - это фактическая битовая комбинация. Для всех вас это может представлять значения от 0 до 255 или от 1000 до 1255.
Типичный цикл чтения InputStream, использующий по одному байту за раз, будет выглядеть следующим образом:
InputStream ips = ...;
int read = 0;
while((read = ips.read()) != -1) {
byte b = (byte)read;
//b will now have a bit pattern ranging from 0x00 to 0xff in hex, or -128 to 127 in two-complement signed representation
}
При запуске высвечивается следующее (использует литералы Java 7 int):
public class Main {
public static void main(String[] args) {
final int i1 = Ox00_00_00_fe;
final int i1 = Ox80_00_00_fe;
final byte b1 = (byte)i1;
final byte b2 = (byte)i2;
System.out.println(i1);
System.out.println(i2);
System.out.println(b1);
System.out.println(b2);
final int what = Ox12_34_56_fe;
final byte the_f = (byte)what;
System.out.println(what);
System.out.println(the_f);
}
}
Как будет ясно из этого, приведение от int к байту просто отбросит все, кроме младших 8 бит. Таким образом, int может быть положительным или отрицательным числом, оно не будет иметь никакого отношения к значению байта. Только последние 8 бит.
Короче говоря: вы получаете правильные значения байтов из вашего InputStream. Реальное беспокойство здесь заключается в том, что если клиентская сторона может быть написана на любом языке программирования и работать на любой платформе, вам необходимо четко указать в своей документации, что означают полученные байты и если они long
, как это закодировано. Дайте понять, что кодирование выполняется в Java с использованием метода ByteBuffer
putLong
с определенным порядком байтов. Только тогда они получат информацию (в сочетании со спецификациями Java), чтобы быть абсолютно уверенными в том, как интерпретировать эти байты.