如何读取java流直到达到特定字节

发布于 2024-09-14 14:08:04 字数 1074 浏览 3 评论 0原文

我的问题与这篇文章类似。但我不发送数据包长度,而是在末尾发送 0 字节。 读取 TCP 流的最有效方法Java

所以我想知道如何编写这样的代码。

目前,我只是使用“

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

如果在您向数据包发送垃圾邮件时正在发送数据包”,它会将尚未到达的数据包视为完全读取的行,但它不完整并且会弄乱整个协议。

在我的协议中,每个数据包都以 0 字节 (0x00) 结尾,以确定单个数据包的结尾(如果数据包最终合并/堆叠在一起)。

所以我真正想做的是继续读取套接字流,直到达到 0x00 为止,这表明数据包已完全制作并准备好进行处理..当然还有某种安全性(我认为超时是最好的)来确定该数据包是垃圾数据包,因为它在特定时间范围(例如 5 秒)内没有以 0 字节结束。

我该怎么做呢?

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
    }

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
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小糖芽 2024-09-21 14:08:04

下面是使用 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() 方法,这是一个重量级方法。

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.

貪欢 2024-09-21 14:08:04
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 的 Ready 函数。您需要检查它是否准备好,如果没有就退出循环。

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.

煮茶煮酒煮时光 2024-09-21 14:08:04

我应该使用 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);
            }

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);
            }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文