2

「サーバー」とクライアントを使用して単純なチャットプログラムを作成しようとしていますが、サーバーからクライアントへ、またはその逆にメッセージを読み込んでいるときにプログラムがブロックされるという問題があります。この例は、クライアントからサーバーへのメッセージの問題を取り上げています。

サーバー側にあるものの例:

private Reader input;
private Writer output;

try {

        server = new ServerSocket(this.port);

        while (true) {

            Socket connection = server.accept();

            serverDisplay("We have a connection");

            input = new BufferedReader(new InputStreamReader(
                    connection.getInputStream()));
            output = new BufferedWriter(new OutputStreamWriter(
                    connection.getOutputStream()));

            int c;
            StringBuffer sb = new StringBuffer();

            // This is where it blocks, the input stream should return -1 at the end of the
            // stream and break the loop, but it doesnt
            while ((c = input.read()) != -1) {
                sb.append((char) c);
            }
            serverDisplay(sb.toString());
        }

    } catch (IOException e) {
        System.out.println("IO ex in the server");
    }

クライアント側でメッセージを送信するために、次のコードがあります。

output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));

private void sendMessage(String message) {
    displayMessage(message);

    try {
        output.write(message);
        output.flush();
    } catch (IOException e) {
        System.out.println("IO ex at sendMessage client");
    }

}

私が送信したすべての文字を読み取ります(クライアントからサーバーへ、Sys outで確認)が、ストリームの最後(-1)を読み取ることになっている場合、そこでハングします

while ループ内に "c" を出力して、返される値を確認しようとしましたが、単にループに入らず、ループを壊さず、そこでハングします。

この主題に関連するいくつかの質問がすでにあることは承知していますが、どの質問にも問題の解決策が見つかりませんでした。

私が使用する場合、奇妙なことに(少なくとも私にとっては):

output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());

と:

while ((message = (String) input.readObject()) != null)

それ以外の:

input = new BufferedReader(new InputStreamReader(connection.getInputStream()));
output = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));

と:

while ((c = input.read()) != -1) 

穴の事は動作します。ただし、これは私がやりたい方法ではなく、BufferedReader/Writer、Input/OutputStreamWriter の API を読み取ることで、コードが機能するはずだと思います。

前もって感謝します。

4

1 に答える 1

6

受信側のストリームの終わりには、送信ストリーム (またはソケット全体) が閉じられるまで到達しません。

output.close()送信側で受信側にストリームの終わりを認識させます。

複数のメッセージにストリームを使用する必要がある場合は、アプリケーション プロトコルにフレーム構造を導入して、受信者がメッセージの境界を決定できるようにする必要があります。これは、メッセージの長さ (バイト単位) を各メッセージの前に付けるのと同じくらい簡単です。

メッセージ全体として文字列を使用しているためです。DataInputStreamデコレータとDataOutputStreamストリーム デコレータを使用して、readUTF()とでメッセージをフレーム化できますwriteUTF(String)writeUTF(String)基本的に、文字列を書き込む前にその長さをストリームに書き込むことで文字列をフレーム化します。readUTF()次に、この長さを読み取り、戻る前にストリームから読み取る必要があるデータの量を認識します。

例:

出力:

DataOutputStream output = new DataOutputStream(connection.getOutputStream());

private void sendMessage(String message) {
    displayMessage(message);

    try {
        output.writeUTF(message);
        output.flush();
    } catch (IOException e) {
        System.out.println("IO ex at sendMessage client");
    }

}

入力:

DataInputStream input = new DataInputStream(connection.getInputStream());

String message = input.readUTF();

serverDispaly(message);
于 2013-10-15T14:06:06.890 に答える