繁体   English   中英

输入流中填充了空数据

[英]Input Stream getting filled with null data

因此,我正在创建一个试图处理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. */
    }
  }
}  

我的问题:是什么导致“侦听”线程循环并无限添加空数据到队列?

虽然我知道这不是Code Review的交流,但是如果有人可以想到更好的类来利用,而他们却只能提及它。

编辑:

根据建议,我将队列从ArrayList<>更改为ArrayBlockingQueue

IOUtils.toByteArray()不适合这种用法。 它将读取到流的末尾并返回一个大字节数组,而不是消息序列。 因此,两次调用或循环调用肯定没有意义。 得到初始结果之后,您可以获得的是无限个空字节数组。

我没有使用过IOUtils.toByteArray但是我怀疑如果调用它时流中没有数据,则它会返回null或一个空数组。

如果考虑一下,这是有道理的,因为否则它不知道要读取多少字节。 它无法知道是否要发送包含1、4或1000个字节的数组,因此它仅在调用时读取已准备就绪的所有内容。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM