0

在使用 Java 7 和 SSL 套接字时,我遇到了一个令人费解的问题。

我有一个客户端/服务器包。两者都使用非常简单的协议相互发送 XML 数据。每条消息的前 4 个字节总是包含整个消息的长度。这意味着,它是 XML 数据的长度加上 4 个字节。

首先,客户端向服务器发送问候消息。接下来,服务器解释问候语并发送响应。然后,客户端本身解释该消息并发送其登录信息。服务器检查该信息并发送回响应。但是这一次,客户端没有收到任何东西,尽管它使用了与从服务器获取问候响应时相同的方法。

这是客户端的简化读取方法:

private String readResponse() throws Exception
{
    BufferedInputStream inputBuffer = new BufferedInputStream(sslSocket.getInputStream());

    // Read and interprete the first 4 bytes to get the length of the XML-data
    int messageLength = readMessageLength(inputBuffer) - 4;

    // PROBLEM OCCURS HERE!

    // Read bufferSize bytes from stream
        byte[] byteArray = new byte[messageLength];
    inputBuffer.read(byteArray);

    // Return the XML-data
    return new String(byteArray);
}

这里是从前 4 个字节中检索长度的方法......

private int readMessageLength(BufferedInputStream in) throws IOException {
    byte[] b = new byte[4];
    in.read(b, 0, 4);

    return (((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff));
}

在客户端应读取第二个响应时,inputBuffer仅包含零 ( [0, 0, 0, 0, 0, 0, ...])。因此,当尝试使用 计算消息长度时readMessageLength(),它会返回-4. 当然,这会导致一个例外。

服务器发送的数据似乎还没有准备好被客户端读取。因此,我做了一些改变:

int messageLength;
do {
    messageLength = readMessageLength(inputBuffer) - 4;
} while(messageLength <= 0);

然而,这也没有奏效。现在是令人费解的部分:发生的情况是这个循环执行了两次!现在分配给的值messageLength来自 XML 数据的前 4 个字节。读取方法返回的字符串现在以 开头?xml,其中<缺少 !

所以,我尝试标记并重置第一个字节: inputBuffer.mark(4);

int messageLength;
do {
    inputBuffer.reset();
    messageLength = readMessageLength(inputBuffer) - 4;
} while(messageLength <= 0);

但这实际上是一个无限循环。由于inputBuffer永远不会改变的内容,messageLength永远不会变成-4.

我什么时候可以确定发送给客户端的数据可用?我怎么能检查呢?什么可能是更好的方法?

问候,沃尔特

PS available() 方法没有用,因为在使用 SSL 套接字时它似乎总是返回零。

4

2 回答 2

4

您必须绝对始终检查从通信通道读取的字节数。它有时可以并且将为零,在这种情况下您必须继续阅读。仅以负返回值到达流的结尾。

具体来说, in.read(new byte[100]) 不一定会读取100 个字节。

如果你想保证你得到了一切,你需要使用 readFully。

于 2012-08-09T13:23:35.550 回答
1
private int readMessageLength(BufferedInputStream in) throws IOException {
    byte[] b = new byte[4];
    int len = in.read(b, 0, 4);
    while(len<4)
        len += in.read(b, len, 4- len);

    return (((b[0] & 0xff) << 24) | ((b[1] & 0xff) << 16) | ((b[2] & 0xff) << 8) | (b[3] & 0xff));
}
于 2012-08-09T13:52:27.990 回答