所以我正在创建一个我试图处理ASCII数据的服务器。虽然我可以让Streams工作并调用方法。然而,监听线程将项添加到队列(ArrayBlockingQueue
),它将循环,直到队列满了空数据。
服务器代码,客户端处理程序(压缩,如果我遗漏了,请告诉我。):
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. */
}
}
}
我的问题:是什么导致&#34;倾听&#34;线程循环并将空数据无限期地添加到队列中?
虽然我知道这不是代码审查交换,但如果有人能想到更好的课程,如果他们可以提及它。
修改
根据建议,我将队列从ArrayList<>
更改为ArrayBlockingQueue
。
答案 0 :(得分:1)
IOUtils.toByteArray()
不适合此用法。它将读取到流的结尾并返回一个大字节数组,而不是一系列消息。因此,调用它两次或循环中肯定没有意义。在初始结果之后,你所能得到的只是无限的空字节数组。
答案 1 :(得分:0)
我没有使用IOUtils.toByteArray
,但我怀疑如果你调用它时流中没有数据,那么它会返回null或空数组。
如果您考虑它,这是有道理的,否则它不知道要读取多少字节。它无法知道您是否正在发送包含1个,4个或1000个字节的数组,因此它只会在您调用时读取所有已准备好的数据。
您需要以某种方式在每次调用toByteArray
之间休眠,并忽略任何空响应。更好的方法是看看你是否可以睡觉,直到更多的数据到达套接字。