Как читать поток Java, пока не будет достигнут определенный байт

Мой вопрос похож на этот пост. Но я отправляю не длину пакета, а 0 байт в конце. Наиболее эффективный способ чтения в потоке TCP в Java

Так что мне интересно, как бы я мог написать что-то подобное.

На данный момент я просто использую

this.socketIn = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
String line = this.socketIn.readLine();

Если пакет отправляется в то время, когда вы рассылаете спам, он будет считать пакет, который еще не прибыл, как полностью прочитанную строку, но она неполная и нарушает работу всего протокола.

В моем протоколе каждый пакет заканчивается байтом 0 (0x00), чтобы определить конец одного пакета, если в случае, если пакеты будут объединены / сложены вместе.

Итак, что я действительно пытаюсь сделать, это продолжать читать поток сокета до тех пор, пока не будет достигнуто значение 0x00, чтобы указать, что пакет полностью создан и готов к обработке ... и, конечно же, какую-то безопасность (я считаю, что лучше всего использовать тайм-аут) для определения пакет является нежелательным, поскольку он не заканчивается нулевым байтом в определенном временном интервале, допустим, 5 секунд.

Как бы я это сделал?

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

Вот что я пробовал до сих пор.

    String line = "";
    int read;
    long timeOut = System.currentTimeMillis();
    while(true) {
        read = this.socketIn.read();
        if (read == -1 || read == 0 || (System.currentTimeMillis()-timeOut) > 5000)
            break;
        line += read
    }

person SSpoke    schedule 16.08.2010    source источник
comment
Что не так с тем, что вы пробовали до сих пор? Кстати, используйте Socket.setSoTimeout (), не увеличивайте свой собственный.   -  person user207421    schedule 17.08.2010
comment
Ха-ха, спасибо EJP, я не знал, что существует команда tmeout.   -  person SSpoke    schedule 17.08.2010


Ответы (3)


Вот скетч с использованием setSocketTimeout для работы со сценарием «медленный клиент / отказ в обслуживании».

this.socket.setSoTimeout(5000);
BufferedReader br = new BufferedReader(
    new InputStreamReader(this.socket.getInputStream()));
StringBuilder sb = new StringBuilder();
try {
    int ch ;
    while ((ch == br.read()) != -1) {
        if (ch == 0) {
            String message = sb.toString();
            // process message
            sb.setLength(0);
        } else {
            sb.append((char) ch);
        }
    }
} catch (InterruptedIOException ex) {
    System.err.println("timeout!"); 
    ...
} finally {
    br.close();
}

Я думаю, что также можно реализовать (жестокий) тайм-аут сокета, создав второй поток, который вызывает socket.close() на объекте сокета, если он обнаруживает, что поток чтения не получает никаких данных. Но это тяжеловесный подход, учитывая более простой setSoTimeout() подход.

person Stephen C    schedule 16.08.2010

InputStreamReader isr = new InputStreamReader(socket.getInputStream());
BufferedReader in = new BufferedReader(isr);
String line = "";
String response = "";
while ((line = in.readLine()) != null) {
    System.out.println(line);
    response = response + line + "\n";
    if (in.ready() == false) {
        break;
    }
}

Уловка - это функция готовности, которая принадлежит BufferedReader. Нужно проверить, готов ли он, если не просто выйти из цикла.

person Joseph Astrahan    schedule 17.08.2012

Стоит ли использовать StringBuilder? или построить свой, как писал EJP. что быстрее?

            String line = "";
            int read;
            //long timeOut = System.currentTimeMillis();
            this.socket.setSoTimeout(5000);
            while(this.socket.isConnected()) {
            read = this.socketIn.read();
            if (read == -1)
                throw new IOException("Insufficient data / timeout)");
            else if(read == 0)
                break;
            line += (char)(read & 0xFF);
            }
person SSpoke    schedule 17.08.2010