Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在不写入任何数据的情况下打开和关闭SSLSocket时出错_Java_Sockets_Ssl - Fatal编程技术网

Java 在不写入任何数据的情况下打开和关闭SSLSocket时出错

Java 在不写入任何数据的情况下打开和关闭SSLSocket时出错,java,sockets,ssl,Java,Sockets,Ssl,简单服务器 listen = getServer(); Logger.getAnonymousLogger().info("Listening to "+listen.toString()); SSLSocket client = (SSLSocket)listen.accept(); // adding this line fixes everything - client.write(42); client.close(); 还有一个简单的客户 SocketFactory sockMake

简单服务器

listen = getServer();
Logger.getAnonymousLogger().info("Listening to "+listen.toString());
SSLSocket client = (SSLSocket)listen.accept();
// adding this line fixes everything - client.write(42);
client.close();
还有一个简单的客户

SocketFactory sockMaker = SSLSocketFactory.getDefault();
Socket server = sockMaker.createSocket("localhost", 1443);
int retval = server.getInputStream().read();
assert retval == -1;
server.close();
如果我没有向SSL套接字写入任何内容,则会在客户端引发异常:

Exception in thread "main" javax.net.ssl.SSLException:\
  Received close_notify during handshake
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190)
我不明白这是为什么。SSL/TLS规范是否要求您将内容写入套接字


请参阅。

您不必将任何内容写入套接字,但如果您立即关闭它,它将生成一个
close\u notify
警报(虽然它被称为“警报”,但这是关闭TLS/SSL套接字的正常方式的一部分)

此外,SSL/TLS套接字被设计为“几乎”像普通TCP套接字一样工作,但由于SSL/TLS的工作方式,有些细节是它们不能(也不能)的。 特别是,在SSL/TLS连接开始时,会发生SSL/TLS握手,这涉及到在发送任何应用程序数据之前从每一方进行的大量读/写操作

报告说:

这张照片上的第一次握手 可以通过以下方式之一启动连接: 三种方式:

  • 调用明确开始握手的开始握手,或
  • 在该套接字上读取或写入应用程序数据的任何尝试都会导致隐式握手,或
  • 调用
    getSession
    尝试在当前没有会话的情况下设置会话 有效会话和隐式 握手完毕
本质上,在您的示例中,客户端的
getInputStream().read()
启动握手,这会导致服务器继续执行
accept()
并在其一侧执行握手。但是,由于您在服务器端关闭了它(通常是立即关闭),因此您甚至没有时间让握手完成。因此,在握手过程中会发送
close\u notify
,这会导致出现异常。如果您尝试从服务器端读写,那么握手至少已经完成

编辑:在@EJP的评论之后,我应该澄清我的意思:

  • createSocket(“localhost”,1443)
    在客户端建立连接,服务器通过
    accept()
    接受连接
  • 客户端的
    getInputStream().read()
    使其启动握手。因此,它向服务器发送
    ClientHello
    TLS消息
  • 由于服务器在接受套接字后直接使用
    close()
    ,因此会发送
    close\u notify
    警报。因为服务器还没有开始读/写,所以它还没有开始握手(因此没有完成握手)
请注意,
SSLServerSocket
实现的目的是创建一个
SSLSocket
,而不一定要对它做任何事情。
SSLServerSocket
对其进行配置,但继续握手超出范围。一方面,这听起来可能使
SSLSocket
的行为更透明,就像普通的TCP套接字一样;另一方面,它意味着从底层TCP流读取数据,因此会产生副作用。 我还没有尝试,但是由
SSLServerSocket
创建的
SSLSocket
可能仍然可以配置为客户端套接字。毕竟正如《圣经》所说: “客户端:启动到服务器的TLS连接的应用程序实体。这可能意味着也可能不意味着客户端启动了底层传输连接。”从API的角度来看,这肯定会对透明度和握手时间产生影响


(为SSL/TLS套接字编写一个映射到普通TCP套接字API的API是一项棘手的工作,Java在这方面做得并不差。真正的“乐趣”从使用
SSLEngine
和NIO通道的异步TLS开始。考虑到任何一方都可以在任何时候发起新的握手,情况会变得更好:就TLS而言,上述级别的含义尚未定义,这可能导致。)

这种情况是无效的。您正在尝试读取未发送的数据。这是一个应用程序协议错误。布鲁诺回答中的所有陈述也适用。客户正在尝试握手;服务器正在尝试关闭连接。可以说,如果还没有握手,服务器close可以发起握手,但事实并非如此


正如您所注意到的,另一种解决方法是在两端调用startHandshake()。

您的命名约定对于
客户端
服务器
套接字是什么有点混淆。此外,客户端代码位于GitHub上的
SSLNullServer
目录中,服务器代码位于
SSLNullClient
目录中。@Bruno,你的观点有效,我的错。关于命名约定,
Socket-client
应该是
Socket-to-client
,这样才有意义。在服务器端关闭之前,您可以使用
addHandshakeCompletedListener
进行同步(不确定这是否是本实验的目标)。至少这可以让你在握手时不发出警告。用一句话来说,问题是,
.close
并不意味着握手。它的意思是“关闭插座,如果没有握手,那就太糟糕了”。我原以为“close”也意味着握手。@Bruno,一个更简单的解决方法是在关闭连接之前在服务器端强制握手。(我正在尝试调试
SSLSocket
中的另一个异常,并尝试了一些简单的情况)。
close
意味着一个
close\u notify
,无论握手是否完成。我不知道为什么
close
暗示握手是有意义的:握手通常用于启动TLS连接或重新协商其某些参数;当您想结束连接时(这是
关闭
的目的),它不是特别有用。@Bruno,我希望
SSLSocket
不允许破坏协议。如果允许关闭连接