【问题标题】:Input Stream getting filled with null data输入流被空数据填充
【发布时间】:2015-12-14 16:04:28
【问题描述】:

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

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

虽然我知道这不是 代码审查 交流,但如果有人能想到更好的类来使用,如果他们能提一下。

编辑:

根据建议,我将队列从 ArrayList&lt;&gt; 更改为 ArrayBlockingQueue

【问题讨论】:

  • @JJF 从我读到的内容来看,输入流应该阻塞,直到数据可用。 (Apache commons 正在使用 read 方法创建字节数组。)我将看一下链接。谢谢。

标签: java multithreading sockets inputstream


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    如果您考虑一下,这是有道理的,否则它不知道要读取多少字节。它无法知道您发送的是包含 1、4 还是 1000 字节的数组,因此它只会读取您调用它时准备好的所有内容。

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

    【讨论】:

    • InputStream.read(byte[] message)使用了read方法,得到了同样的结果。 IOUtils.toByteArray 只是 read() Stream 方法的掩码,所以我相信这不是问题。
    • 它读取到流的末尾,而不是“当你调用它时所有准备好的东西”。 @Gamerb 这不是“简单地说,read() 方法的掩码”。如果是的话,使用它就没有什么意义了。
    猜你喜欢
    • 1970-01-01
    • 2013-05-11
    • 1970-01-01
    • 2018-03-08
    • 2020-06-23
    • 2022-01-16
    • 1970-01-01
    • 2020-02-06
    • 1970-01-01
    相关资源
    最近更新 更多