整个代码都很复杂,所以我直接说到了这一点。 代码如下
SSLContext ctx = SSLContext.getInstance("TLS");
如果您为getInstance(字符串协议)方法阅读docs,则说明
This method traverses the list of registered security Providers, starting
with the most preferred Provider. A new SSLContext object encapsulating
the SSLContextSpi implementation from the first Provider that supports the
specified protocol is returned.
Note that the list of registered providers may be retrieved via the
Security.getProviders() method.
对我来说,Security.getProviders()方法提供了以下提供者
现在我已经验证“TLS”协议位于com.sun.net.ssl.internal.ssl.Provider
(索引2)并始终被选中。
但是相应的SSLContextSpi对象在Java 6和Java 7中有所不同。在java 6中我得到com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9
而在java 7中我得到sun.security.ssl.SSLContextImpl$TLS10Context@615ece16
。这有非常糟糕的效果,因为稍后我创建SSL套接字时它们属于不同的类。
那为什么会这样呢?有工作吗?我希望封装在com.sun.net.ssl.internal.ssl.SSLContextImpl@7bbf68a9
上下文中的com.sun.net.ssl.internal.ssl.Provider
SSLContextSpi对象相同(在两种情况下都相同)。
答案 0 :(得分:5)
这会产生非常糟糕的影响,因为稍后我创建SSL套接字时,它们属于不同的类。
这不是错误的效果。您从公共API中的工厂获得的实际课程由JRE实施决定:这些具体类不是公共API的一部分。
您在Java 6和Java 7之间获得不同的类并不重要。即使它们具有相同的名称,如果将它们相互比较也没有意义。
修改强>
当我给它一个时,当你得到这个时,Java 7中的
public int read(byte[] b)
函数只读取1个字节 长度为4的字节数组,我也确认有4个 流中的字节。
SSLSocket
表现正常。实际上,它可能表现得更好,因为这个初始的1字节读取是由BEAST-prevention measure引起的。我会将自己的答案复制并粘贴到那个问题上,因为你犯了同样的错误。
您正在尝试阅读byte[]
与您在另一端编写它们的假设是典型的TCP错误。它实际上并不特定于SSL / TLS,但也可能发生TCP连接。
在TCP(以及SSL / TLS)中无法保证读取器的缓冲区将填充与写入器缓冲区中的数据包完全相同的数据包长度。所有TCP保证都是按顺序交付,因此您最终将获得所有数据,但您必须将其视为流。
这就是为什么使用TCP的协议依赖于指示符和分隔符来告诉另一端何时停止阅读某些消息。
例如,HTTP 1.1使用空行来指示标头何时结束,并使用Content-Lengt
h标头告诉收件人期望的实体长度(或分块传输编码)。 SMTP还在邮件末尾使用行返回和.
。
如果您正在设计自己的协议,则需要为收件人定义一种方式,以便知道您定义的有意义的数据单元何时被分隔。当您读取数据时,请阅读此类指示符,并填写读取缓冲区,直到获得预期的字节数或直到找到已定义的分隔符为止。