缓冲套接字读取器不等待来自远程连接的数据

时间:2013-03-10 19:37:28

标签: java io

我有一个从TCP源读取数据的Java程序都工作正常,除非我的程序(充当数据源的客户端)速度快,然后源可以响应BufferedReader.ready()抛出异常它应该关闭我的TCP连接。是否有任何首选的方法/方法可以让BufferedReader等待新的输入,因为我的源有时会有轻微的延迟。

以下是我所谈论的部分:

 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 个答案:

答案 0 :(得分:0)

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

Javadoc for Readerready()方法描述为:

  

判断此流是否可以读取。

     

返回:如果保证下一个read()不阻止输入,则返回true,false   除此以外。注意,返回false并不能保证下一个   读将阻止。

更糟糕的是,如果读者在返回之前等待更多数据,如果您尝试从中读取,则Reader.ready()将返回false。这样做意味着Reader已经完成,实际上你应该期望这个方法在使用网络流时经常返回false,因为它很容易有延迟。 / p>

您的代码当前可能正在读取一行(在do块中),然后检查读取器是否准备好(在while中),它可能不是,然后成功退出。没有异常被抛出 - 如果有的话,你会看到SEVERE级别的日志消息。

不要使用ready(),而是利用readLine()所记录的行为表明它返回:

  

包含该行内容的String,不包括任何内容   行终止字符,如果流结束,则为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?