Ошибка сокета Java в Linux (отправлено 0xFF, получено -3) - PullRequest
4 голосов
/ 12 мая 2010

Работая на сервере WebSocket в Java, я столкнулся с этой странной ошибкой. Я сократил его до двух небольших файлов Java, один из которых является сервером, а другой - клиентом. Клиент просто отправляет 0x00, строку Hello, а затем 0xFF (согласно спецификации WebSocket).

На моем компьютере с Windows сервер печатает следующее:

Listening
byte: 0
72 101 108 108 111 recieved: 'Hello'

На моем Unix-сервере тот же код печатает следующее:

Listening
byte: 0
72 101 108 108 111 -3

Вместо получения 0xFF он получает -3, никогда не выходит из цикла и никогда не печатает то, что получил.

Важная часть кода выглядит следующим образом:

byte b = (byte)in.read();
System.out.println("byte: "+b);

StringBuilder input = new StringBuilder();
b = (byte)in.read();
while((b & 0xFF) != 0xFF){
 input.append((char)b);
 System.out.print(b+" ");
 b = (byte)in.read();
}
inputLine = input.toString();

System.out.println("recieved: '" + inputLine+"'");
if(inputLine.equals("bye")){
 break;
}

Я также загрузил два файла на свой сервер:

Мой компьютер с Windows работает под управлением Windows 7, а мой компьютер с Linux работает под управлением Debian

Edit:
Когда b является int, он все еще действует странно. Я отправляю 0xFF (255), но получаю 65533 (не 65535 или 255).

Ответы [ 4 ]

12 голосов
/ 12 мая 2010

Проблема не в коде, который вы показали. Это здесь:

in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

Вы имеете дело с двоичными данными , поэтому вам следует использовать необработанный поток - не превращайте его в Reader, который предназначен для чтения символов .

Вы получаете 65533, потому что это целое число, используемое для «символа замены Unicode», используемого, когда значение не может быть представлено как реальный символ Unicode. Точное поведение вашего текущего кода будет зависеть от кодировки символов по умолчанию в вашей системе - что опять-таки не то, на что вам следует полагаться.

Далее, вы предполагаете, что каждый байт должен переводиться в один символ - по сути, вы принимаете ISO-8859-1. Я не проверял спецификацию, но сомневаюсь, что это то, что вы должны использовать.

Наконец, вы не проверяете, является ли b -1, что указывает на то, что клиент закрыл поток.

3 голосов
/ 02 ноября 2011

Решение, отличное от описанного выше Джоном, просто определите кодировку как ISO-8859-1. По умолчанию Java использует UTF-8.

in = new BufferedReader(newInputStreamReader(kkSocket.getInputStream(),"ISO-8859-1"));

Таким образом, Java будет правильно интерпретировать байты как символы, которые вы намеревались сделать.

Это необходимо, потому что 0xFF, который является вашим последним байтом, является недопустимым символом в UTF-8. Другой вариант - установить для Java кодировку по умолчанию ISO-8859-1. http://en.wikipedia.org/wiki/UTF-8#Codepage_layout

Я помню, как Java сменила исключение на замену символа символом замены (int 65533).

0 голосов
/ 13 мая 2010

И ваша проверка EOS неверна. Вы должны прочитать в int и сравнить его с -1. Если true, вы достигли конца потока, поэтому закройте сокет или, скорее всего, выходной поток, и продолжайте соответствующим образом. В противном случае приведите его к байту. В настоящий момент вы не можете передать 0xff, потому что он будет обрабатываться так же, как EOS.

0 голосов
/ 12 мая 2010

Байт со значением -3 имеет битовую комбинацию 11111101. И со значением -3 имеет битовую комбинацию 11111111111111111111111111111101

Итак, вы получаете по существу то же значение. Хотелось бы мне понять, почему вы получаете -3.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...