Я создал SocketChannel для удаленного сервера для отправки и получения сообщений на Tomcat. Чтобы получать сообщения с удаленного компьютера, я использовал поток, посвященный задаче (только этот поток будет читать из сокета, ничего больше).Java SocketChannel Eating my bytes
Когда некоторые байты принимаются в SocketChannel (я продолжаю опрос SocketChannel в режиме без блокировки для новых данных), я сначала прочитал 4 байта, чтобы получить длину следующего сообщения, а затем выделить и прочитать x байтов из SocketChannel, который затем декодируется и реконструируется в сообщение.
Ниже мой код для получающего потока:
@Override
public void run() {
while (true) { //Don't exit thread
//Attempt to read the size of the incoming message
ByteBuffer buf = ByteBuffer.allocate(4);
int bytesread = 0;
try {
while (buf.remaining() > 0) {
bytesread = schannel.read(buf);
if (bytesread == -1) { //Socket was terminated
}
if (quitthread) break;
}
} catch (IOException ex) {
}
if (buf.remaining() == 0) {
//Read the header
byte[] header = buf.array();
int msgsize = (0xFF & (int)header[0]) + ((0xFF & (int)header[1]) << 8)
+ ((0xFF & (int)header[2]) << 16) + ((0xFF & (int)header[3]) << 24);
//Read the message coming from the pipeline
buf = ByteBuffer.allocate(msgsize);
try {
while (buf.remaining() > 0) {
bytesread = schannel.read(buf);
if (bytesread == -1) { //Socket was terminated
}
if (quitthread) break;
}
} catch (IOException ex) {
}
parent.recvMessage(buf.array());
}
if (quitthread) {
break;
}
}
}
Первые байты, которые я получил от SocketChannel это хорошо, и я успешно расшифровал сообщение. Однако в следующий раз, когда я прочитал из SocketChannel, сокет пропустил около 100 байт, что заставило ошибочные байты читать и интерпретировать как длину, в результате чего все стало поврежденным.
Что не так с кодом? Ни одна другая нить не читается из SocketChannel.
Вместо того чтобы преобразовать буфер заголовка в 4 байта, вы можете просто вызвать getInt() на нем, чтобы прочитать длину. Если вы хотите рассматривать это как unsigned int, вы всегда можете отбрасывать длинный и побитовый AND с 0xFFFFFFFF. Кроме того, – Adamski
Я, вероятно, могу, хотя я не был уверен, что java будет читать arr [4] byte [] как немного endian. В любом случае, я сомневаюсь, что это является причиной проблемы. Первая длина сообщения правильная, и я прочитал это количество байтов. Проверка сообщения чтения также не указала ошибок. Проблема только в том, что я пытаюсь прочитать следующие 4 байта для заголовка. – futureelite7