Сервер выдает исключение OutOfMemory при чтении байтового массива из TCP-соединения

Я все еще работаю на моем сервере push! Я успешно реализовал шифрование с использованием javax.crypto.cipher. Это требует, чтобы я читал / записывал байты в поток сокета. Я могу отправлять и получать просто отлично. Шифрование работает. Но когда по воздуху ничего не происходит, сервер генерирует исключение OutOfMemoryException. Функция readBytes:

public static byte[] readBytes() throws IOException {
    int len = dis.readInt();
    byte[] data = new byte[len];
    if (len > 0) {
        dis.readFully(data);
    }
    return data;
}

Код, который вызывает это:

 public String read() {
            byte[] encrypted,decrypted = null;
            try {
                    encrypted = readBytes();
                    if (encrypted.equals(new Byte[] {0})) return "";
                    if (encrypted.equals(null)) return null;
                    cipher.init(Cipher.DECRYPT_MODE, key);
                    decrypted = cipher.doFinal(encrypted);
            } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
            }
            String afterEncryption = new String(decrypted);
            return afterEncryption;
    }

И read() вызывается в цикле while:

while (true&loggedin&((inputLine=read())!=null)) {

И исключение, которое выдается:

Exception in thread "ServerThread" java.lang.OutOfMemoryError: Java heap space
    at ServerThread.readBytes(ServerThread.java:277)
    at ServerThread.read(ServerThread.java:245)
    at ServerThread.run(ServerThread.java:108)

Строка 277 является той, которая объявляет байтовый массив. Функция, которая отправляет байтовый массив:

    public static void sendBytes(byte[] myByteArray, int start, int len) throws IOException {
    if (len < 0)
        throw new IllegalArgumentException("Negative length not allowed");
    if (start < 0 || start >= myByteArray.length)
        throw new IndexOutOfBoundsException("Out of bounds: " + start);
    if (len > 0) {
        dos.writeInt(len);
        dos.write(myByteArray, start, len);
    }
}

sendBytes запускается только тогда, когда read() прекращает блокировку. Вот так и работает цикл.

Если этот код выглядит знакомым, то это потому, что я нашел его при переполнении стека!

Рукопожатие работает безупречно, но как только оно перестает отправлять сообщения, я получаю исключение примерно через пять секунд.

Спасибо за любую помощь, которую вы можете оказать мне.

1 ответ

Решение

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

Для этого вам действительно следует использовать CipherInputStream и CipherOutputStream: они выполняют для вас большую часть этой тяжелой работы. Или даже SSL.

Другие вопросы по тегам