2

我已经实现了一个帮助模块,它让我从与 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 的通道

问题是选择器卡在第 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,然后最终关闭套接字,但即使这样也没有帮助。

任何想法?

4

2 回答 2

3

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

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

于 2011-07-17T02:21:29.617 回答
1

我建议is.close();在拳头断言之前添加。

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

于 2009-06-04T17:37:30.673 回答