0

タイプ Key の公開鍵オブジェクトをサーバーに送信しようとしています。しかし、私はこれを実行しませんでした。プロトコルは次のようになります。

[コマンド]\n[シリアル化されたキー オブジェクト]

クライアントは次のコードを使用します。

Socket admin;
PrintWriter pw;
OutputStream os;
BufferedReader is; 
for(int tries = 0; tries < MAX_RECONNECT_TRIES_ADMIN_SERVER; tries++)
{
    try 
    {
        admin = new Socket(host,port);
        os = admin.getOutputStream();
        is = new BufferedReader(new InputStreamReader(admin.getInputStream()));
        pw = new PrintWriter(new OutputStreamWriter(os));   

        AdminServerCommand.NODE_REGISTER.writeToPrintWriter(pw);
        pw.flush();

        sendPublicKey(os);

        String resultLine = null;
        resultLine = is.readLine();
        if(AdminServer.Feedback.KEY_REGISTERED.commandMatch(resultLine))
        {
            is.close();
            os.close();
            admin.close();
            return true;
        }
        is.close();
        os.close();
        admin.close();
        registerNodeRetrySleep(1000);
    }
    catch (Exception e) 
    {}
}
return false;

public void sendPublicKey(OutputStream out)
{
    try
    {
        ObjectOutputStream outO = new ObjectOutputStream(out);
        outO.writeObject(cyper.getPublicKey());
        outO.flush();
    }
    catch (Exception ex)
    {
        ex.printStackTrace();
    }
}

public void writeToPrintWriter(PrintWriter os)
{
    if(os == null)
        throw new IllegalArgumentException("Can not write command to null stream.");
    os.println(comm);
    os.flush();
}

サーバーが使用する

String com = "";
    try 
    {
        if(client.getInputStream().available() > 2)
        com = is.readLine();
    }
    catch (IOException e) 
    {
        errorResponse(Error.COMMAND_ERROR);
    }
    Key key = null;
    try
    {
        ObjectInputStream keyIn = new ObjectInputStream(client.getInputStream());
        key = (Key)keyIn.readObject();
    }
    catch(Exception b)
    {
        b.printStackTrace();
        errorResponse(Error.BAD_KEY);
        return;
    }

例外は次のようになります。

Nov 28, 2012 9:52:59 PM AdminServer.AdminServer run
INFO: Get a new request
java.io.StreamCorruptedException: invalid stream header: 73720014
    at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
    at java.io.ObjectInputStream.<init>(Unknown Source)
    at AdminServer.AdminServer.registerNewKeyEntry(AdminServer.java:115)
    at AdminServer.AdminServer.run(AdminServer.java:65)
    at java.lang.Thread.run(Unknown Source)
Nov 28, 2012 9:52:59 PM AdminServer.AdminServer errorResponse
WARNING: Error: Bad public key format. Use object stream with key object.

どうすればこれを解決できますか?Key 型は、Interface Serializable 自体を実装する Interface 型です。したがって、このオブジェクトをシリアル化しても問題はありません。私はこの問題で一晩中過ごします。誰でもこれを取り除くのを手伝ってくれることを願っています。

4

1 に答える 1

1

質問には完全に診断するのに十分なコードがありませんが、ここにいくつかの観察があります。

このコードは疑わしいようです:

if(client.getInputStream().available() > 2)
com = is.readLine();

おそらくis、クライアント入力ストリームをラップするバッファリングされたリーダーがあるとします。if ステートメントが真でない場合はどうなりますか?行を読み飛ばしますか? このテキスト行はまだパイプラインにあり、keyIn.readObject メソッドに渡されます。これにより、破損したエラーが発生する可能性があります。

行全体を削除することをお勧めしifます。とにかく readLine() はブロックするので、チェックの必要はありません。

AdminServerCommand.NODE_REGISTER.writeToPrintWriter(pw);また、 が改行の後にまったく文字を含まない 1 行のテキストを送信すると確信していますか?

ただし、ここにはもっと大きな問題があると思います。Java オブジェクトのシリアライゼーションと手動でのテキストの読み取り/書き込みを行ったり来たりするこの設計は、まさに災害が起こるのを待っています。オブジェクトのシリアル化を使用する場合は、排他的に使用してください。String オブジェクトを交互に送信してから Key オブジェクトを送信すると、改行が 1 つまたは 2 つ少ないためにストリームが破損することはありません。

例: ObjectOutputStream outO = new ObjectOutputStream(out);

    String command = "whatever";
    outO.writeObject(command);
    outO.writeObject(cyper.getPublicKey());
    outO.flush();

次にサーバー側では、最初はコマンド、2 番目はキーになることを認識して、常に readObject を使用します。

于 2012-11-28T21:25:51.883 に答える