我正在尝试使用SSL编写一个简单的echo服务器。转到服务器的第一行完全回应。当我发送第二行时,只回显第一个字符。客户端使用stdin的缓冲读取器读取线。如果我再次点击CR,则会显示其余信息。服务器似乎正在发送所有数据。以下是客户端和服务器的输出:
客户端:
发送到服务器192.168.0.161 在9999端口
4 seasoNS
回声:4 seasoNS
非常好
回音:一个
回声:真的很好
SERVER:
服务员收听9999
有cr / lf
4 seasoNS
发送大小:10
有cr / lf
非常好
发送大小:16
退出......
这是客户端循环:
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();
}
这个问题看起来很奇怪,我希望有一些明显的东西让我失踪。
答案 0 :(得分:3)
你所看到的是完全正常的。
你一直认为你要一次性读取整个缓冲区的假设是错误的:
int sz = srvrStream.read(srvrData);
相反,你需要保持循环,直到你得到你选择的分隔符(在你的情况下可能是一个新行)。
这通常适用于普通TCP连接以及SSL / TLS连接。这就是为什么应用程序协议必须具有分隔符或内容长度的原因(例如,HTTP有一个双重新行来结束其标题并使用Content-Length
或分块传输编码在实体结束时告诉另一方。)
在实践中,你可能看不到你的假设何时对这么小的例子起作用。
然而,JSSE将它发送的记录拆分为1 / n-1({3}}。 (OpenSSL会发送0 / n。) 因此,在这种情况下,问题会更加明显。
同样,这不是SSL / TLS或Java问题,修复此问题的方法是将您读取的输入视为流而不是假设您在一端读取的缓冲区大小将与用于从另一端发送数据的缓冲区。