How to read java stream until certain byte is reached

12,922

Solution 1

Here's a sketch using setSocketTimeout to deal with the "slow client / denial of service" scenario.

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();
}

I think it is also possible to implement a (brutal) socket timeout by creating a second thread that calls socket.close() on the socket object if it detects that the reading thread is not getting any data. But that's a heavyweight approach, given the simpler setSoTimeout() approach.

Solution 2

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;
    }
}

The trick is the ready function that belongs to the BufferedReader. You need to check if it's ready, if not just get out of the loop.

Share:
12,922
SSpoke
Author by

SSpoke

Pro programmer from the russia How to be a programmer in steps? 1). Set a goal what you wish to program.. 2). Make your program just work. (don't worry think much how messy your coding is.) 3). Fix all bugs you can find and do tests on each part to make sure no more bugs exist. 4). Finally start from scratch and re-write your program in a clean matter, this will be fast don't worry because you already did this once ;). 4). And always ask StackOverflow for advise on parts you are unsure.

Updated on June 09, 2022

Comments

  • SSpoke
    SSpoke almost 2 years

    My question is similar to this post. But I don't send packet length rather a 0 byte at end. Most efficient way to read in a tcp stream in Java

    So I'm wondering how would I code something that would.

    At the moment I just use

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

    If packet is getting sent while you are spamming the packet it's going to count the packet which hasn't arrived yet as a fully read Line, yet it's incomplete and messes up the whole protocol.

    In my protocol each packet is ended with a 0 byte (0x00) to determine the end of a single packet if in case packets end up merged/stacked together.

    So what I'm trying to do really is keep reading the socket stream until a 0x00 is reached to indicate the packet is fully crafted and ready for processing.. and of course some kind of security (a timeout is best I believe) to determine the packet is junk as it's not ended in a 0 byte in a specific time frame lets say 5 seconds.

    How would I go about doing this?

    P.S> I'm not using NIO framework but just a regular thread per connection socket and I don't want to switch to NIO as it's very difficult to inject data with a completely different global thread that processes updates and sends specific updates to random users (not broadcast).

    Here is what I tried so far.

        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
        }