SSLEngine并关闭

时间:2009-05-28 15:44:05

标签: java networking ssl nio sslengine

我已经实现了一个辅助模块,它允许我从与SSL一起使用的通道中获取干净的数据并将加密的数据写入其中:这是相关的接口(我在该类中也有一些非抽象的方法,所以没有不要告诉我“DataProvider应该是一个接口”;)):

public abstract class DataProvider {
    // Notify the bytes read from the net
    public abstract void readFromNet(ByteBuffer b);
    // Gets the bytes to write into the net
    public abstract void writeToNet(ByteBuffer b);
    // Add a message to send
    public abstract boolean addMessage(byte[] data);
    // Obtains the application data received
    public abstract byte[] getReceivedApplicationData();
    // True if there is something to actually send over the wire
    public abstract boolean dataToSend();
    // True if we should close the channel
    public abstract boolean shouldClose();
    // Notify our intention to shut down the connection
    public abstract void shutDown(SelectionKey sk);
    // Set the interest op set for the channel
    public abstract void setInterestOps(SelectionKey sk);
}

我是SSL的抽象基类的实现。 在测试该实现时,我写了两个函数:在一个我收到带有SocketChannel的消息和用于发送数据的SSLSocket关闭连接,在另一个我发送消息与SocketChannel启动关闭。 现在,问题是用于接收数据的SSLSocket没有关闭,即使我已经发布了这些步骤:

  1. engine.closeOutbound()
  2. engine.wrap()
  3. channel.write(data)(是的,我确定我已经发送了使用wrap()获得的所有数据
  4. 选择用于读取入站close_notify
  5. 的频道

    问题是选择器在第4步中卡住了。

    在另一个测试中(SSLSocket关闭连接)我没有问题。

    请注意,我已将shouldClose实现为:

    return engine.isOutboundDone() && engine.isInboundDone();
    

    所以我需要一个传入的close_notify来关闭,即使我已经初始化了关闭(我不知道这是否正确:最终我可以用return engine.isOutboundDone()更改它)

    这是我的SSLSocket方面代码:

    Socket toRead = socket.accept();
    toRead.setSoTimeout(0);
    InputStream is = toRead.getInputStream();
    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    String read = "";
    byte[] barray = new byte[1024];
    while (read.length() < toSend.length() * 2) {
        int bytesRead = is.read(barray);
        bos.write(barray, 0, bytesRead);
        read = new String(bos.toByteArray());
    }
    assertEquals(toSend + toSend, read);
    assertTrue(toRead.isClosed());
    

    违反了最后一个断言。

    最初我认为这是因为没有与toRead关联的“后台”线程,所以我应该用它来读取/写入以便使用传入的close_notify然后最终得到套接字关闭,但即使这样也无济于事。

    有什么想法吗?

2 个答案:

答案 0 :(得分:3)

答案非常晚,但如果您已经发送了一个,则不需要等待close_notify,请参阅RFC 2246.但是您应该得到一个。你没有说明你在close_notify上的确切选择。

注意您的代码没有意义。只有关闭套接字时才会关闭套接字。 isClosed()指的是套接字,而不是连接。

答案 1 :(得分:1)

我建议在第一个断言之前添加is.close();

请注意,我建议的这一小段代码不会关闭套接字。它应该关闭InputStream。