Java: как абстрагироваться между обычным TCP Socket и SSLSocket

Изменить: удалено startHandshake();, так как оно не имеет отношения к вопросу и редко требуется (например, не в моем случае)

У меня есть довольно специфический и редкий протокол клиент-сервер (через TCP).
Я реализовал его с помощью SSLSocket.
Теперь я предвижу, что мне может понадобиться использовать тот же протокол для незашифрованного соединения.

Моя проблема в том, что класс, реализующий протокол, имеет поле: public SSLSocket currentSocket;
(и тогда методы в моем клиентском классе делают всевозможные .read(), .write(), flush()...)

Я думал изменить тип поля, например так: public Socket currentSocket;
Однако тогда проблема в том, что моя процедура подключения несовместима:

public static void connect () {
currentSocket = SslUtils.getSSLsocket(host, port, keystoreFile, keystorePass, pkPass);
...
  • Конструктор по умолчанию java.net.Socket явно не принимает материалы хранилища ключей

Я не хочу переделывать весь клиент только из-за этой разницы...

  • У меня есть одна мысль: когда мне нужен сокет с открытым текстом, создать SSLSocket без шифрования.
    Я не знаю, является ли это профессиональным способом и будет ли он вообще работать (сервер будет ожидать открытый текст). клиентский сокет в новом варианте использования)

  • Моя другая идея состоит в том, чтобы определить два поля, одно для сокета с открытым текстом, одно для сокета SSL, а затем использовать логику для связывания входящих/исходящих потоков с правильным полем по мере необходимости. Однако это приведет к «висячему» полю. Если вы используете SSL, будет лишнее поле Socket plaintextSocket и наоборот...

Есть ли способ сделать мое поле currentSocket более абстрактным, чтобы я мог определить его в том же клиенте, а затем указать немного другой путь кода клиента в зависимости от известной переменной (что-то вроде needSSLsocket=true) для создания экземпляра и подключения?


person DraxDomax    schedule 27.01.2020    source источник
comment
(1) Вы можете написать свою собственную фабрику, которая создает требуемый сокет, и (2) вам не нужно вызывать startHandshake(). Вы должны быть в состоянии написать все свое приложение с точки зрения Socket, кроме того, что происходит в фабричном методе, если только вы не делаете причудливые вещи, такие как аннулирование сеанса или повторное подтверждение.   -  person user207421    schedule 28.01.2020
comment
@user207421 user207421 Я думал о своей собственной фабрике, но похоже, что это больше суеты, чем того стоит. Я получил довольно хорошо сдержанные варианты использования. Насчет startHandShake - боюсь, я тут пленник невежества. Я не знаю, как подключить SSL-сокет без него. В любом случае, спасибо за ваш ценный вклад!   -  person DraxDomax    schedule 28.01.2020
comment
startHandshake() вызывается автоматически при первом вводе/выводе в/из сокета. Вы не должны называть это сами. Вам нужно вызывать его только тогда, когда вы хотите изменить сеанс.   -  person user207421    schedule 29.01.2020
comment
@ user207421 ДА! Я просто закомментировал, что рукопожатие и все работает как обычно :) Честно говоря, при разработке моего клиента мне пришлось столкнуться с таким количеством вещей, что я не подвергал сомнению каждое руководство, которое смог найти. В моем стиле разработки на одно действие меньше - спасибо ‹3   -  person DraxDomax    schedule 29.01.2020


Ответы (1)


SSLSocket расширяет Socket, поэтому вы можете назначить объект SSLSocket переменной Socket. Вы правы, изменяя поле currentSocket на Socket. Просто используйте другую переменную для обработки SSLSocket, когда это необходимо, например:

public static void connect () {
    if (needSSLsocket) {
        SSLSocket ssl = SslUtils.getSSLsocket(host, port, keystoreFile, keystorePass, pkPass);
        ssl.startHandshake();
        ...
        currentSocket = ssl;

        /* or:
        currentSocket = SslUtils.getSSLsocket(host, port, keystoreFile, keystorePass, pkPass);
        ((SSLSocket) currentSocket).startHandshake();
        ...
        */
    } else {
        currentSocket = new Socket(host, port);
    }
    ...
}
person Remy Lebeau    schedule 27.01.2020
comment
Проверено и принято. Спасибо! Я просто добавлю комментарий о startHandshake(); - person DraxDomax; 29.01.2020
comment
Хорошо, это редактирование было отклонено, но для будущих читателей: startHandshake(); , как показано в моем вопросе и не имеет к нему отношения, может не быть неотъемлемой частью процедуры подключения к сокету SSL, за исключением редких случаев. - person DraxDomax; 29.01.2020
comment
@DraxDomax startHandshake(); , как показано в моем вопросе и не имеет к нему отношения - тогда вы должны были вообще исключить это из обсуждения. - person Remy Lebeau; 29.01.2020
comment
честно говоря, я думал, что могу оставить его там. Поскольку, с объективной точки зрения, другому кодировщику действительно может понадобиться вызвать этот метод, и он показывает, что вы не можете выполнить с объектом Socket, что добавляет импульс к объединению типов. Но черт с ним спорить с 400к :) Буду редактировать. В очередной раз благодарим за помощь - person DraxDomax; 29.01.2020