开发者

How to read java stream until certain byte is reached

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.开发者_如何学JAVA

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
    }


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.


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.


Should I use StringBuilder? or build my own as EJP wrote. which is faster?

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜