【问题标题】:How to read java stream until certain byte is reached如何读取java流直到达到某个字节
【发布时间】:2022-03-09 00:33:54
【问题描述】:

我的问题与这篇文章类似。但我最后不发送数据包长度,而是一个 0 字节。 Most efficient way to read in a tcp stream in Java

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

目前我只是使用

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

如果在您向数据包发送垃圾邮件时发送数据包,它会将尚未到达的数据包视为完全读取的线路,但它不完整并会破坏整个协议。

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

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

我该怎么做呢?

附注> 我没有使用 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
    }

【问题讨论】:

  • 到目前为止您的尝试有什么问题?顺便说一句,使用 Socket.setSoTimeout(),不要自己开发。
  • 哈哈谢谢 EJP 我不知道 tmeout 命令存在。

标签: java sockets stream packet


【解决方案1】:

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

【讨论】:

    【解决方案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;
        }
    }
    

    诀窍是属于 BufferedReader 的 ready 函数。您需要检查它是否已准备好,如果没有退出循环。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-06
        • 1970-01-01
        • 1970-01-01
        • 2017-04-27
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 2019-01-25
        相关资源
        最近更新 更多