输入流填充空数据

时间:2015-12-14 16:04:28

标签: java multithreading sockets inputstream

所以我正在创建一个我试图处理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

2 个答案:

答案 0 :(得分:1)

IOUtils.toByteArray()不适合此用法。它将读取到流的结尾并返回一个大字节数组,而不是一系列消息。因此,调用它两次或循环中肯定没有意义。在初始结果之后,你所能得到的只是无限的空字节数组。

答案 1 :(得分:0)

我没有使用IOUtils.toByteArray,但我怀疑如果你调用它时流中没有数据,那么它会返回null或空数组。

如果您考虑它,这是有道理的,否则它不知道要读取多少字节。它无法知道您是否正在发送包含1个,4个或1000个字节的数组,因此它只会在您调用时读取所有已准备好的数据。

您需要以某种方式在每次调用toByteArray之间休眠,并忽略任何空响应。更好的方法是看看你是否可以睡觉,直到更多的数据到达套接字。