0

ハードウェア デバイスとのクライアント ソケット接続を行っています。ハードウェアによって処理されるように、この接続にコマンドを送信しています。ここで、確認または応答として、ハードウェアが応答を送信します。アプリケーションは、たとえば 10 秒で定期的にコマンドを接続に送信します。

現在、応答がアプリケーションから送信されたコマンドと同期されないというランダムな問題が存在します。これはハードウェア固有のものと考えていましたが、驚いたことに、同じポートで同じハードウェアにパテを接続して応答を見ると、応答が常に同期されていることがわかります。これは、リクエストをレスポンスにマッピングするためにいくつかの基準を使用する内部のパテのように見えます。

以下は、ハードウェア デバイスにコマンドを送信するために使用しているプログラミング手順です。

            Socket clientSocket = new Socket(<IPADDRESS>, 4001);
    DataOutputStream outToServer = new DataOutputStream(
            clientSocket.getOutputStream());
    BufferedReader inFromServer = new BufferedReader(new InputStreamReader(
            clientSocket.getInputStream()));
    while (true) {
        try {
                            //Get command randomly from array enums for test
            Random r = new Random();
            Commands[] array = Commands.values();
            String command = (String) array[r
                    .nextInt(Commands.values().length)].getCommand();
            outToServer.writeBytes(command);
            Thread.sleep(500);
            while (!inFromServer.ready()) {
            }
            System.out.println("COMMAND "+command+", SERVER RESPONSE: "
                    + inFromServer.readLine());
            Thread.sleep(1500);

        } catch (SocketTimeoutException se) {
            //Handle Exception
        } catch (SocketException se) {
            //Handle Exception
        }

パテのようなメカニズムとして、リクエストとレスポンスの同期をどのように達成できるかアドバイスをいただけますか?

4

2 に答える 2

1

パテはあなた以上にあなたのデバイスについて知りません。問題はあなたのコードにあります。テストready()sleep(). readLine()デバイスが回線を送信することが確実な場合は、 を呼び出します。そうでない場合は、単に呼び出しますInputStream.read().

于 2013-08-16T09:47:51.897 に答える
1

スレッドのスリープを削除し、read を次のように書き換えます。

String line;
while ((line = inFromServer.readLine()) != null) {
    System.out.println("COMMAND "+command+", SERVER RESPONSE: "
                + line);
}

デバイスが改行文字なしで最後のメッセージを送信すると、このコードはハングする可能性があります\n。元のコードは入力をスキップしました。

主な問題は次の行にあります。

 while (!inFromServer.ready()) { 

InputStreamReader#readyすべてのデータが送信されたことを知る他の手段がある場合にのみ使用しても問題ありません。

このストリームを読み取る準備ができているかどうかを示します。InputStreamReader は、その入力バッファーが空でない場合、または基になるバイト ストリームからバイトを読み取ることができる場合、準備ができています。

最初のメッセージは読み取られますが、それによってバッファーが空になり、2 番目のメッセージが到着すると、コードは読み取れなくなります。デバイスからのメッセージと同じ数のループが必要になりますが、それは少なくとも実用的ではありません。その場合も、おそらく常に機能するとは限りません。

一方、BufferedReader#readLine

戻り値:

行終了文字を含まない、行の内容を含む文字列、またはストリームの末尾に到達した場合は null

送信されたすべてのデータが読み取られるまで読み取ります。ただし、デバイスが改行文字を送信しない場合、このメソッドは行を読み取ることはありません。コードはバッファ内のすべてのデータでハングします。その場合InputStreamReader#read、EJP が提案するように使用する必要があります。

戻り値:

読み取った文字、またはストリームの終わりに達した場合は -1

IO Streamsの公式チュートリアルを読むことを強くお勧めします。

一般的に言えば、待機はビジー待機(空のステートメントの実行) では行われません。たとえば、次のようになりますThread.sleep

while (true) {}  /*or*/ while(true);

CPU は空のステートメントを実行しており、このステートメントが完了するのを待っている間、他の作業を行っている可能性があります。それは悪い習慣です。

待機を実装する方法について詳しく知りたい場合は、公式の同時実行チュートリアルを読むか、この問題に関するより広範なアプローチについてこれを読むことをお勧めします。

于 2013-08-16T09:48:10.850 に答える