java 如何读取java流直到达到某个字节
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3498126/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to read java stream until certain byte is reached
提问by SSpoke
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
我的问题类似于这篇文章。但我不发送数据包长度,而是在末尾发送 0 字节。 在 Java 中读取 tcp 流的最有效方法
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.
在我的协议中,每个数据包都以 0 字节 (0x00) 结束,以确定单个数据包的结尾,以防数据包最终合并/堆叠在一起。
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.
所以我真正想做的是继续读取套接字流,直到达到 0x00 以指示数据包已完全制作并准备好进行处理......当然还有某种安全性(我认为最好是超时)来确定数据包是垃圾,因为它没有在特定时间范围内以 0 字节结束,比如说 5 秒。
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).
PS> 我没有使用 NIO 框架,而只是每个连接套接字的常规线程,我不想切换到 NIO,因为很难用一个完全不同的全局线程来注入数据,该线程处理更新并向随机用户发送特定更新(不是广播)。
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
}
回答by Stephen C
Here's a sketch using setSocketTimeout to deal with the "slow client / denial of service" scenario.
这是使用 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();
}
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.
我认为也可以通过创建第二个线程来实现(残酷的)套接字超时,socket.close()如果它检测到读取线程没有获取任何数据,则调用套接字对象。但考虑到更简单的setSoTimeout()方法,这是一种重量级的方法。
回答by Joseph Astrahan
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.
诀窍是属于 BufferedReader 的就绪函数。你需要检查它是否准备好了,如果没有就退出循环。
回答by SSpoke
Should I use StringBuilder? or build my own as EJP wrote. which is faster?
我应该使用 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);
}

