2013-03-10 50 views
-5

我有一个Java程序从TCP源读取数据的工作都很好,除非我的程序(它充当数据源的客户端)比那时更快源可以响应BufferedReader.ready()抛出一个异常,它会关闭我的TCP连接,因为它应该如此。是否有任何首选的方法/方法可以让BufferedReader等待新的输入,因为我的源有时可能会有轻微的延迟。缓冲套接字读取器不等待远程连接的数据

这是我讲的一部分:你不应该使用ndataServerReader.ready()

public aDataServer(String host, int port, StreamConnection aConnection) throws UnknownHostException, IOException { 
      this.aConnection = aConnection; 
      ndataServerSocket = new Socket(Inet4Address.getByName(host),port); 
      ndataServerReader = new BufferedReader(new InputStreamReader(ndataServerSocket.getInputStream())); 
     } 


public void run() { 
      try { 
       RemoteDevice dev = RemoteDevice.getRemoteDevice(aConnection); 
       OutputStream outputStream = aConnection.openOutputStream(); 
       OutputStreamWriter osw = new OutputStreamWriter(outputStream); 
       do { 
        try { 
         String ndata = ndataServerReader.readLine(); 


          osw.write(ndata+"\n"); 
          osw.flush(); 
          LOG.log(Level.INFO,"Sent"); 


        } catch(IOException io) { 
         LOG.log(Level.SEVERE, "Client device({0}) disconnected: \n{1}", new Object[]{dev.getFriendlyName(true), io.getMessage()}); 
         break; 
        } 
       }while(ndataServerReader.ready()); 
      } catch (IOException ioe) { 
       LOG.severe(ioe.getMessage()); 
      } finally { 
       try { 
        if (ndataServerSocket != null) { 
           ndataServerSocket.close(); 
        } 
        if (ndataServerReader 
          != null) { 
           ndataServerReader.close(); 
        } 
       } catch (IOException ex) { 
        LOG.log(Level.SEVERE, ex.getMessage()); 
       } 
      } 
+1

什么是抛出异常?你能否包含你如何构建和读取BufferedReader的代码片段? – dimo414 2013-03-10 19:43:19

+0

用一些代码更新了我的问题 – user1945235 2013-03-10 19:53:04

+0

您是否也可以发布异常输出? – dimo414 2013-03-10 19:58:38

回答

0

。你的do/while循环(几乎肯定只是一个while循环)似乎假设ndataServerReader.ready()表示有更多的数据要读取,这不是它的用途。

Javadoc for Reader描述ready()方法为:

判断此流是否已准备好被读取。

返回:如果下一个read()保证不会阻塞输入,则返回true,否则返回false 。请注意,返回false并不能保证读取的下一个 将被阻止。

在其他情况下,如果读者在尝试从中读取数据时将返回之前等待更多数据,则Reader.ready()将返回false。这是而不是意味着读者已完成,事实上你应该期望这种方法经常在使用网络流时返回false,因为它可能很容易出现延迟。

您的代码当前有可能读取一行(在do区块中),然后检查读取器是否已准备就绪(在while中),这可能不是,然后成功退出。没有任何例外 - 如果是的话,你会看到SEVERE级别的日志消息。

而不是使用ready()的,采取的说,它返回的readLine()的记录的行为的优势:

包含行的内容,不包括任何 行终止字符的字符串,或NULL,如果该流的末尾已经达到

换句话说,简单地做:

String ndata = reader.readLine(); 
while (ndata != null) { 
    osw.write(ndata+"\n"); 
    osw.flush(); 
    LOG.log(Level.INFO,"Sent"); 

    ndata reader.readLine(); 
} 

足以读取整个输入流。

参考阅读:What's the difference between (reader.ready()) and using a for loop to read through a file?

+0

谢谢,现在更加合理。如果我正确理解这一点,这也不会在等待时造成巨大的CPU使用量。 – user1945235 2013-03-10 21:47:40

+0

不应该,线程只是等待(在一个循环中有效地执行'Thread.sleep()',尽管实际的实现是本地OS代码),直到它从源获得足够的数据,或者它比允许的超时,你可以在Socket对象中设置,在这种情况下会抛出一个异常,表示没有足够的数据返回。 – dimo414 2013-03-10 21:59:24