为什么我的客户端在使用SSL套接字和Java 7时无法读取服务器发送的第二条消息?

Wal*_*ter 1 java sockets ssl bufferedinputstream

使用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);
}
Run Code Online (Sandbox Code Playgroud)

这里是从前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));
}
Run Code Online (Sandbox Code Playgroud)

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

似乎很明显,服务器发送的数据尚未准备好被客户端读取.因此,我做了一些改变:

int messageLength;
do {
    messageLength = readMessageLength(inputBuffer) - 4;
} while(messageLength <= 0);
Run Code Online (Sandbox Code Playgroud)

但是,这也不起作用.现在出现了令人费解的部分:发生的事情是这个循环执行了两次!分配给messageLength现在的值来自XML数据的前4个字节.read-method返回的字符串现在以缺少的?xml地方开头<!

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

int messageLength;
do {
    inputBuffer.reset();
    messageLength = readMessageLength(inputBuffer) - 4;
} while(messageLength <= 0);
Run Code Online (Sandbox Code Playgroud)

但这实际上是一个无休止的循环.由于inputBuffer永不改变的内容,messageLength永远不会成为别的东西-4.

我何时可以确定发送给客户的数据是否可用?我该怎么检查?什么是更好的方法?

此致,沃尔特

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

Ros*_*son 5

绝对必须始终检查从通信通道读取的字节数.它有时也可能为零,在这种情况下你必须继续阅读.仅使用负返回值达到流结束.

具体而言,in.read(新字节[100])将必然读取100个字节.

如果你想保证你得到了所有东西,你需要使用readFully.