7

単一のソケット (並列読み取りおよび書き込み操作をサポートする) で動作する読み取りおよび書き込みループをどのように設計しますか? 複数のスレッドを使用する必要がありますか? 私の(Java)ソリューションは良いですか?そのスリープコマンドはどうですか?そのようなループ内でそれをどのように使用しますか?

私は2つのスレッドを使用しようとしています:

読んだ

public void run() {
    InputStream           clientInput;
    ByteArrayOutputStream byteBuffer;
    BufferedInputStream   bufferedInputStream;
    byte[]                data;
    String                dataString;
    int                   lastByte;

    try {
        clientInput         = clientSocket.getInputStream();
        byteBuffer          = new ByteArrayOutputStream();
        bufferedInputStream = new BufferedInputStream(clientInput);

        while(isRunning) {  

            while ((lastByte = bufferedInputStream.read()) > 0) {
                byteBuffer.write(lastByte);
            }
                data       = byteBuffer.toByteArray();  
                dataString = new String(data);
                byteBuffer.reset();     
        }   

    } catch (IOException e) {
        e.printStackTrace();
    }
}

書く

public void run() {
    OutputStream clientOutput;
    byte[]       data;
    String       dataString;

    try {
        clientOutput = clientSocket.getOutputStream();

        while(isOpen) { 

            if(!commandQueue.isEmpty()) {
                dataString = commandQueue.poll();
                data       = dataString.getBytes();
                clientOutput.write(data);
            }                   
            Thread.sleep(1000);
        }       
        clientOutput.close();           
    } 
    catch (IOException e) {
        e.printStackTrace();
    } 
    catch (InterruptedException e) {
        e.printStackTrace();
    }
}

-1 が送信されないため、読み取りは適切な結果を提供できません。この問題を解決するにはどうすればよいですか?

このスリープ/書き込みループは良い解決策ですか?

4

2 に答える 2

4

ネットワークI/Oを実行するには、基本的に3つの方法があります。

  1. ブロッキング。このモードでは、読み取りと書き込みは実行されるまでブロックされるため、両方を同時に実行する場合は、それぞれに個別のスレッドが必要です。

  2. ノンブロッキング。このモードでは、読み取りと書き込みは、実行できない場合にゼロ(Java)または一部の言語(C)でステータス表示(return == -1、errno = EAGAIN / EWOULDBLOCK)を返すため、個別のスレッドは必要ありません。ただし、操作をいつ実行できるかを通知する3番目のAPIが必要です。select()これがAPIの目的です。

  3. 非同期I/O。転送をスケジュールし、転送のステータスを問い合わせることができるある種のハンドル、またはより高度なAPIではコールバックが返されます。

ここで使用している/スタイルは絶対に使用しないでください。正しい使い方はほとんどなく、これはその1つではなく、睡眠は文字通り時間の無駄です。データはスリープ時間内に到着する可能性があり、通常はすぐにウェイクアップします。while (in.available() > 0)sleep()InputStream.available()read()

于 2012-04-25T09:54:26.957 に答える
0

while(true)の代わりにブール変数を使用して、必要なときにスレッドを適切に閉じる必要があります。また、はい、新しいデータが受信されるまでスレッドはそれ自体をブロックするため、接続されているクライアントごとに1つずつ、複数のスレッドを作成する必要があります(たとえば、DataInputStream()。read()を使用)。いいえ、これは実際には設計上の質問ではありません。各ライブラリ/フレームワークまたは言語には、ソケットからリッスンする独自の方法があります。たとえば、Qtのソケットからリッスンするには、「シグナルとスロット」と呼ばれるものを使用する必要があります。無限ループ。

于 2012-04-25T09:21:32.737 に答える