Я пытаюсь подключить приложение Android к серверу с поддержкой SSL, который использует самозаверяющий сертификат. Я уже прочитал десятки руководств, и теперь приложение принимает сертификат и подключается к серверу, но я никогда не получаю никаких данных обратно.
Исходный код, который я использовал для инициализации сокета, следующий:
//passphrase for keystore
char[] keystorePass="password".toCharArray();
//load own keystore (MyApp just holds reference to application context)
KeyStore keyStore=KeyStore.getInstance("BKS");
keyStore.load(MyApp.getStaticApplicationContext().getResources().openRawResource(R.raw.keystore),keystorePass);
//create a factory
TrustManagerFactory trustManagerFactory=TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keyStore);
//get context
SSLContext sslContext=SSLContext.getInstance("TLS");
//init context
sslContext.init(
null,
trustManagerFactory.getTrustManagers(),
new SecureRandom()
);
//create the socket
Socket socket=sslContext.getSocketFactory().createSocket("hostname",443);
socket.setKeepAlive(true);
После этого цикл выполнения потока-получателя использует socket.getInputStream () для доступа к входному потоку. Пока я использую незашифрованное соединение, это работает без проблем. Но безопасное соединение не извлекает никаких данных из сокета. Я проверил это, добавив сообщения журнала в цикл приема и даже использовал для проверки s_server OpenSSL. Я получил данные от клиента, но клиент так и не получил ничего, что я ему отправил.
В качестве последнего теста я попытался открыть соединение с www.google.com:443 следующим образом:
javax.net.SocketFactory fact=SSLSocketFactory.getDefault();
Socket socket=fact.createSocket(_config.getUri().getHost(), _config.getUri().getPort());
По-прежнему тот же результат, соединение работает, но с использованием InputStream я ничего не получаю от сервера.
У кого-нибудь есть идеи?
РЕДАКТИРОВАТЬ:
В настоящее время мне не разрешено отвечать на свой вопрос, но вот ответ:
Что ж, оказывается, проблема заключалась в петле приема. Я полагался на InputStream.available ()
, чтобы получить количество байтов для чтения, но не понимал, что это ненадежно (всегда возвращает 0 для сокета SSL).Поэтому я переключил цикл приема на использование блокировки read ()
.