在套接字上使用ObjectStreams来传输Java密钥对象

时间:2012-11-28 20:57:10

标签: java sockets exception serialization

我正在尝试将Key类型的公钥对象发送到我的服务器。但我没有得到这个运行。 prototocl看起来如下:

[Command] \ 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;
    }

Exception看起来如下:

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。所以序列化这个对象应该不是问题。我整个晚上都有这个问题。希望有人能帮我摆脱这个。

1 个答案:

答案 0 :(得分:1)

您的问题中没有足够的代码可以完全诊断 - 但这里有一些观察结果。

此代码看起来很可疑:

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

据推测,您有一个缓冲的阅读器is包装客户端输入流。如果if语句不正确会发生什么 - 你跳过阅读该行?现在,该行文本仍在管道中,并将传递给您的keyIn.readObject方法。这可能会导致腐败错误。

我建议只删除整个if行。 readLine()会阻塞,所以不需要检查。

另外,您是否绝对确定AdminServerCommand.NODE_REGISTER.writeToPrintWriter(pw);只发送一行文字,换行后绝对没有字符?

然而 - 我认为你在这里有更大的问题。这种在Java对象序列化和手动文本读/写之间来回切换的设计只是一场等待发生的灾难。如果要使用对象序列化,请仅使用它。你可以替换发送一个String对象,然后一个Key对象,你的流不会被破坏,因为你发送了太多或一两个换行符。

例如:         ObjectOutputStream outO = new ObjectOutputStream(out);

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

然后在服务器端,总是使用readObject,知道第一个是命令,第二个是密钥。