Java 输入流被空数据填充
因此,我正在创建一个服务器,试图处理ASCII数据。而我可以让流工作并调用方法。但是,侦听线程需要将项目添加到队列(Java 输入流被空数据填充,java,multithreading,sockets,inputstream,Java,Multithreading,Sockets,Inputstream,因此,我正在创建一个服务器,试图处理ASCII数据。而我可以让流工作并调用方法。但是,侦听线程需要将项目添加到队列(ArrayBlockingQueue),它将循环,直到队列中满是空数据 服务器代码,客户端处理程序(压缩,如果我遗漏了什么,请告诉我): 我的问题:是什么导致“侦听”线程循环并无限期地向队列添加空数据? 虽然我知道这不是代码审查交换,但如果有人能想到更好的类来利用,如果他们能提到的话 编辑: 根据一项建议,我将队列从ArrayList更改为ArrayBlockingQueue我没有
ArrayBlockingQueue
),它将循环,直到队列中满是空数据
服务器代码,客户端处理程序(压缩,如果我遗漏了什么,请告诉我):
我的问题:是什么导致“侦听”线程循环并无限期地向队列添加空数据?
虽然我知道这不是代码审查交换,但如果有人能想到更好的类来利用,如果他们能提到的话
编辑:
根据一项建议,我将队列从
ArrayList
更改为ArrayBlockingQueue
我没有使用IOUtils.toByteArray
,但我怀疑,如果调用时流中没有数据,那么它要么返回null要么返回空数组
如果您仔细考虑,这是有意义的,因为否则它不知道要读取多少字节。它无法知道您是否正在发送包含1、4或1000字节的数组,因此它只会在您调用它时读取所有准备就绪的内容
您需要在每次调用
toByteArray
之间以某种方式休眠,并忽略任何空响应。更好的方法是查看是否可以在更多数据到达套接字之前睡眠。IOUtils.toByteArray()
不适合此用法。它将读取到流的末尾,并返回一个大字节数组,而不是一个消息序列。因此,毫无疑问,调用它两次或在循环中调用它是没有意义的。在初始结果之后,您只能得到无限多个空字节数组。@JJF根据我所读的内容,输入流应该阻塞,直到数据可用为止。(apachecommons正在使用read方法创建字节数组。)我将查看链接。谢谢。您使用了InputStream.read(byte[]message)
的读取方法,并收到了相同的结果。IOUtils.toByteArray
只是read()
Stream方法的一个掩码,所以我相信这不是问题所在。它读取到流的末尾,而不是“调用它时准备好的所有东西”@Gamerb它不是“简单地说,read()
方法的掩码”。如果是的话,使用它就没有什么意义了。
class ClientThread extends Thread {
// ASCII commands defined here (byte NUL=0x00; byte SOH=0x01; etc.)
private Socket socket;
private InputStream sInput;
private OutputStream sOutput;
BlockingQueue<byte[]> queueIn = new ArrayBlockingQueue<>(30, true);
private boolean goodToGo = false;
ClientThread(Socket socket){
id = ++Server.uniqueId; /* To be replaced with UIDs */
this.socket = socket;
/* Create Data Streams */
try {
sInput = (socket.getInputStream());
sOutput= (socket.getOutputStream());
goodToGo = true;
} catch (IOException ex) {
ServerInit.logger.log(Level.WARNING, "Error Openning Streams!", ex);
}
}
@Override
public void run(){
boolean keepGoing = true;
System.out.println("Client thread started.");
/* Start listening thread */
new Thread() {
@Override
public void run(){
while(goodToGo) {
System.out.println("Listening thread looping.");
try {
byte[] temp = IOUtils.toByteArray(sInput); // read client input using Apache Commons IO.
// Add the result to the queue.
queueIn.put(temp);
} catch (EOFException eof){
ServerInit.logger.log(Level.INFO,"Remote client closed connection.");
close();
}
catch (IOException ex) {
ServerInit.logger.log(Level.WARNING, "Error Reading Stream!", ex);
close();
}
}
}
}.start();
while (keepGoing && goodToGo){
System.out.println("Main thread looping.");
try{
byte[] message = queueIn.take();
if (message.length >= 4){
/* Message picked apart and worked with here */
} else if (message.length == 0 ){
// Do nothing.
} else {
ServerInit.logger.log(Level.WARNING, "Unable to process item from queue.");
}
} catch (Exception e) {
/* Here just for completeness, I don't catch Exceptions this way. :) */
}
}
}
protected void close(){
// try to close the conection
goodToGo = false;
try {
if (sOutput != null) {
sOutput.close();
}
if (sInput != null) {
sInput.close();
}
if (socket != null) {
socket.close();
}
ServerInit.SERVER.remove(id);
} catch (Exception e){
ServerInit.logger.log(Level.FINER, "Error closing client connections.", e);
}
}
}
public class TestClient{
public static void main(String args[]){
try{
Socket socket = new Socket("localhost", 5525);
OutputStream outputStream = socket.getOutputStream();
byte[] buffer = { 0x02, 0x05, 0x07, 0x04 };
outputStream.write(buffer);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
/* Again, I don't catch exceptions like normally. */
}
}
}