5

サーバーに接続しているクライアントがあります。サーバーとクライアントは、文字列形式でデータを交換します。問題は、サーバーがメッセージの最後に「\n」文字を使用しないため、クライアントがreadLine()メソッドでブロックされていることです。残念ながら、サーバー側は変更できません。最後に '\n' がないようなメッセージをストリームから読み取るにはどうすればよいですか?

私のクライアントコード:

public class json 
{

    private static Socket socket;

    public static void main(String args[])
    {

        String sendMessage = "";

        Gson gson = new Gson();
        JSON_package authentication = new JSON_package();
        authentication.setType("Identifying");
        authentication.setSource("exampleClient");

        Package_Parser pp = new Package_Parser();

        sendMessage = gson.toJson(authentication);


        sendMessage = authentication.buildPackage(sendMessage);

        try
        {
            String host = "host_address";
            int port = port_number;
            InetAddress address = InetAddress.getByName(host);

            System.out.println("Connecting.");

            socket = new Socket(address, port);
            System.out.println("Connected.");

            //Send the message to the server
            OutputStream os = socket.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os);
            BufferedWriter bw = new BufferedWriter(osw);
            bw.write(sendMessage);
            bw.flush();
            System.out.println("Message sent to the server : "+sendMessage);

            //Get the return message from the server
            InputStream is = socket.getInputStream();
            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            StringBuffer buffer = new StringBuffer();
            String message = br.readLine();

            message = pp.Parser(message);

            System.out.println("Message received from the server : " +message);
        }
        catch (Exception exception) 
        {
            exception.printStackTrace();
        }
        finally
        {
            //Closing the socket
            try
            {
                socket.close();
                System.out.println("Closed.");
            }
            catch(Exception e)
            {
                e.printStackTrace();
            }
        }
    }
}
4

3 に答える 3

5

readyおよびread(char c)メソッドの使用を試みることができます。以下に一例を示します。

StringBuffer sb = new StringBuffer();
while (br.ready()) {
    char[] c = new char[] { 1024 };
    br.read(c);
    sb.append(c);
}
于 2013-07-17T21:46:54.157 に答える
1

最も簡単な解決策は、文字ごとにメッセージを読み取ることですが、ここでの主な問題は、メッセージがいつ完了したかを知ることです。行指向のプロトコルでは、これは単純です。送信された改行は、メッセージ間の「セパレーター」です。そうしないと、この問題を簡単に解決できる状況が 2 つあります。

ケース 1: メッセージの末尾には常に固定文字があり、メッセージ内では発生しません。

// let's pretend ! is the end of message marker
final char endMarker = '!';

// or of course StringBuffer if you need to be treadsafe
StringBuilder messageBuffer = new StringBuilder();
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
    char c = (char)value;
    // end?  jump out
    if (c == endMarker) {
        break;
    }
    // else, add to buffer
    messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();

ケース 2: メッセージの長さが固定の場合

// let's pretend message is always 80 long
int messageLength = 80;

StringBuilder messageBuffer = new StringBuilder();
int charactersRead = 0;
// reads to the end of the stream or till end of message
while((value = br.read()) != -1) {
    char c = (char)value;
    // end?  jump out
    if (++charactersRead >= messageLength) {
        break;
    }
    // else, add to buffer
    messageBuffer.append(c);
}
// message is complete!
String message = messageBuffer.toString();

どちらの場合も、受け取った内容の健全性をチェックするコードを追加する必要があります。読み取り中に EOF を受け取った可能性があります。

明確なメッセージ区切りがなく、メッセージの長さが可変である場合は、はるかに困難になります。

于 2013-07-17T21:47:02.410 に答える
0

ポイントはreadLine()、入力が改行で終わることが実際に保証されているデータを読み取ることです。一般に、入力を解析するときは、何らかのトークン(入力内の文字または文字の組み合わせ) が存在する必要があります。

  • さらに入力を待つ
  • すでに得た情報で何かをする
    • そして、後でさらに入力を待つことに戻るかどうかを決定する可能性があります

改行が送信されることを保証できない場合はreadLine()、ジョブに適したツールではありません。代わりに、文字配列読み取りメソッドのようなものを使用してください。InputStreamReader読み込んだ文字の配列を反復処理し、作業するのに十分な入力があるときを把握する必要があります。また、一度に 1 文字のread()方法を使用することもできます。この方法ではInputStreamReader、コードは単純になりますが、おそらく効率が低下します。

の文字配列バージョンを使用し、read()一部を解析した後に入力の収集に戻る場合は、次のラウンドで処理するために、解析するのに十分な量を取得したときに残ったものをキューに戻すことを忘れないでください。

于 2013-07-17T22:09:08.153 に答える