简体   繁体   English

读取SSL套接字Java的奇怪行为

[英]Odd behavior reading SSL socket Java

I am trying to write a simple echo server using SSL. 我正在尝试使用SSL编写一个简单的echo服务器。 The first line that goes to the server is echoed exactly. 转到服务器的第一行完全回应。 When I send a second line, only the first character is echoed. 当我发送第二行时,只回显第一个字符。 The client works off of a buffered reader's read line from stdin. 客户端使用stdin的缓冲读取器读取线。 If I hit CR again the rest of the message comes through. 如果我再次点击CR,则会显示其余信息。 The server seems to be sending all of the data. 服务器似乎正在发送所有数据。 Here are output from client and server: 这是客户端和服务器的输出:

CLIENT: 客户:

Sending to server at 192.168.0.161 on port 9999 在端口9999上发送到服务器192.168.0.161

4 seasoNS 4 seasoNS
echo:4 seasoNS 回声:4 seasoNS

are really good 非常好
echo:a 回声:一

echo:re really good 回声:真的很好

SERVER: server listening on 9999 SERVER:服务器监听9999
has cr/lf 有cr / lf
4 seasoNS 4 seasoNS

size to send: 10 发送大小:10
has cr/lf 有cr / lf
are really good 非常好

size to send: 16 发送大小:16
exiting... 退出...

Here is the client loop: 这是客户端循环:

        try {
        BufferedReader consoleBufferedReader = getConsoleReader();
        sslsocket = getSecSocket(strAddress, port);
        BufferedWriter sslBufferedWriter = getSslBufferedWriter(sslsocket);
        InputStream srvrStream = sslsocket.getInputStream();

        String outMsg;
        while ((outMsg = consoleBufferedReader.readLine()) != null) {
            byte[] srvrData = new byte[1024];
            sslBufferedWriter.write(outMsg);
            sslBufferedWriter.newLine();
            sslBufferedWriter.flush();
            int sz = srvrStream.read(srvrData);
            String echoStr = new String(srvrData, 0, sz);
            System.out.println("echo:" + echoStr);
        }
    } catch (Exception exception) {
        exception.printStackTrace();
    }

This problem seemed so odd that I was hoping there was something obvious that I was missing. 这个问题看起来很奇怪,我希望有一些明显的东西让我失踪。

What you're seeing is perfectly normal. 你所看到的是完全正常的。

The assumption you're making that you're going to read the whole buffer in one go is wrong: 假设您要一次性读取整个缓冲区是错误的:

int sz = srvrStream.read(srvrData);

Instead, you need to keep looping until you get the delimiter of your choice (possibly a new line in your case). 相反,你需要保持循环,直到你得到你选择的分隔符(在你的情况下可能是一个新的行)。

This applies to plain TCP connections as well as SSL/TLS connections in general. 这通常适用于普通TCP连接以及SSL / TLS连接。 This is why application protocols must have delimiters or content length (for example, HTTP has a double new line to end its headers and uses Content-Length or chunked transfer encoding to tell the other party when the entity ends). 这就是为什么应用程序协议必须具有分隔符或内容长度的原因(例如,HTTP有一个双重新行来结束其标题,并使用Content-Length或chunked transfer encoding在实体结束时告诉另一方)。

In practice, you might not see when your assumption doesn't work for such a small example. 在实践中,您可能看不到何时您的假设不适用于这么小的例子。

However, the JSSE splits the records it sends into 1/n-1 on purpose to mitigate the BEAST attack . 但是,JSSE会将它发送的记录拆分为1 / n-1, 以减轻BEAST攻击 (OpenSSL would send 0/n.) Hence, the problem is more immediately noticeable in this case. (OpenSSL将发送0 / n。)因此,在这种情况下,问题更加明显。

Again, this is not an SSL/TLS or Java problem, the way to fix this is to treat the input you read as a stream and not to assume the size of buffers you read on one end will match the size of the buffers used to send that data from the other end. 同样,这不是SSL / TLS或Java问题,修复此问题的方法是将您读取的输入视为流,而不是假设您在一端读取的缓冲区大小将与用于的缓冲区大小相匹配从另一端发送数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM