-5

私は TCP ソースからデータを読み取る Java プログラムを持っていますが、私のプログラム (データ ソースへのクライアントとして機能する) がより速く、ソースが応答できる場合を除いて、すべて正常に動作します。必要に応じて 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());
                }
            }
4

1 に答える 1

0

を使用しないでくださいndataServerReader.ready()。do/while ループ (ほぼ確実に while ループである必要があります) はndataServerReader.ready()、読み取るデータが他にもあることを示していると想定しているように見えますが、これは目的ではありません。

ReaderのJavadoc では、このready()メソッドについて次のように説明されています。

このストリームを読み取る準備ができているかどうかを示します。

戻り値: 次の read() が入力に対してブロックされないことが保証されている場合は true、それ以外の場合は false。false を返すことは、次の読み取りがブロックされることを保証しないことに注意してください。

さらに悪いことにReader.ready()、リーダーから読み取ろうとした場合、リーダーが戻る前にさらにデータを待つ場合、false が返されます。これはReader が完了したことを意味するものではありませ。実際、ネットワーク ストリームを操作する場合、このメソッドは頻繁に false を返すことを予期する必要があります。これは、遅延が発生しやすいためです

現在、コードは 1 行 (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();
}

入力ストリーム全体を読み取るには十分です。

参考資料: (reader.ready()) と for ループを使用してファイルを読み取ることの違いは何ですか?

于 2013-03-10T20:37:12.110 に答える