Я реализовал вспомогательный модуль, который позволяет мне получать чистые данные из канала, используемого с 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, используемый для получения данных, не закрывается, даже если я выполнил следующие шаги:
- engine.closeOutbound ()
- engine.wrap ()
- channel.write (data) (да, я уверен, что отправил все данные, полученные с помощью wrap ()
- выбор канала для чтения входящих сообщений close_notify
Проблема в том, что селектор застрял на 4-м шаге.
В другом тесте (SSLSocket закрывает соединение) у меня нет проблем.
Обратите внимание, что я реализовал mustClose как:
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
, а затем, наконец, закрыть сокет, но даже это не помогает.
Есть идеи?