有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

socket如何读取java流,直到达到某个字节

我的问题与这篇文章类似。但我不发送数据包长度,而是在末尾发送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)结尾,以确定单个数据包的结尾,以防数据包合并/堆叠在一起

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

我该怎么做呢

p.S>; 我没有使用NIO框架,只是每个连接socket使用一个常规线程,我不想切换到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
    }

共 (3) 个答案

  1. # 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. # 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. # 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);
                }