您不必这样写任何东西,但是如果立即关闭它,它将生成
close_notify警报(尽管它被称为“警报”,但这是关闭TLS /
SSL套接字的常规方法的一部分)。
另外,SSL / TLS套接字被设计为“几乎”像普通的TCP套接字一样工作,但是由于SSL /
TLS的工作方式,有一些细节它们不能(也不能)。尤其是,在SSL / TLS连接开始时,会发生SSL /
TLS握手,这涉及在发送任何应用程序数据之前从每一方进行的多次读取/写入。
SSLSocket的文档说:
可以通过以下三种方式之一启动此连接上的初始握手:
startHandshake明确开始握手的呼叫,或者- 尝试在此套接字上读取或写入应用程序数据会导致隐式握手,或者
getSession如果没有当前有效的会话,则调用尝试建立会话,并且隐式握手已完成。
本质上,
getInputStream().read()您的示例中的客户端发起了握手,这导致服务器继续进行
accept()
。但是,由于您通常在服务器端将其关闭(通常是立即关闭),因此您甚至没有时间完成握手。因此,
close_notify在握手期间发送,这会导致您得到异常。如果您尝试从服务器端进行读取或写入,则握手至少已经完成。
编辑 :在@EJP的评论之后,我应该澄清一下我的意思:
createSocket("localhost", 1443)客户端上的客户端建立连接,服务器通过接受连接accept()
。getInputStream().read()
在客户端使它发起握手。因此,它将ClientHello
TLS消息发送到服务器。- 因为服务器
close()
在接受套接字后立即使用,所以它会发送close_notify
警报。因为服务器尚未开始读取/写入,所以它尚未开始握手(因此无法完成握手)。
需要注意的是目的
ServerSocket.accept(),这
SSLServerSocket工具,是创建一个
SSLSocket,不一定用它做任何事情。该
SSLServerSocket配置,但诉讼与握手的范围了。一方面,听起来像是使
SSLSocket行为像普通的TCP套接字一样更加透明。另一方面,它意味着从底层TCP流中读取数据,因此会产生副作用。我还没有尝试过,但是仍然可以将
SSLSocketby创建的
SSLServerSocket配置为
client socket 。毕竟,如RFC
2246词汇表所述:
“客户端:启动与服务器的TLS连接的应用程序实体。这可能或可能不意味着客户端启动了基础的传输连接。”
从API的角度来看,这绝对会影响透明度以及何时进行握手。
(编写用于SSL /
TLS套接字的API映射到普通TCP套接字的API是一项艰巨的工作,Java并不会为此做得太糟糕。真正的“乐趣”始于使用
SSLEngine和NIO通道的异步TLS
。考虑到任何一方都可以随时发起新的握手,甚至会变得更好:就TLS而言,以上级别的含义尚未定义,这可能会导致尴尬的问题。)



