Создание сервера на базе Qt с использованием ssl сертификатов. Часть 2

4.95 (2)

В предыдущей части  мы написали простейший  обработчик подключений и класс, объекты которого будут обрабатывать эти подключения. 

Для того что бы наш сервер, как то реагировал на другие события, кроме как обрабатывал одно подключения, его нужно вынести в отдельный поток. Но при таком подходе при большом количестве подключений будет создано много потоков и Ваша система просто рухнет. Что бы обезопасить себя необходимо использовать пул потоков, или просто ограничить количество подключаемых клиентов. Но  это уже в следующий раз опишем, а сейчас напишем наш обработчик подключений, добавив при этом в перечисление  enum class Error строчку, которая говорит о коде ошибку, если у нас что то пошло не так с сокетом. 


SOCKET_SETUP_ERROR  = 2
	

обработчик подключений:


void SslServer::incomingConnection(qintptr handle)
    {
        qDebug()<<"incomingConnection on socket:"<setSocket(handle)) {

            //создаем новый поток и запускаем его
            QThread* threadForClient = new QThread();
            clientConnection->moveToThread(threadForClient);
            threadForClient->start();

        } else {
            /*
             * если нам не удалось по какойто причине установить сокет
             * то освобождаем ресурсы и посылаем сигнал чо у нас ошибка на серве,
             * с кодом Error::SOCKET_SETUP_ERROR
             * 
             */
            qDebug()<<"socket setup error;";
            delete clientConnection;
            emit error(Error::SOCKET_SETUP_ERROR);
        }

    }

	

Теперь, если мы запустим наш сервер и попытаемся к нему подключится(через тот же телнет), то мы увидим информацию об ошибках и предупреждениях. 

error_on_sslserver


И это вполне нормально, ведь мы указали что для соединения мы используем ключи. Если открыть документацию по перечислению   QAbstractSocket::SocketError, то мы увидим следующее:


13	The SSL/TLS handshake failed, so the connection was closed (only used in QsslSocket)
	

Что означает что при установки соединения возникла ошибка с так называемым ssl рукопожатием. 

На этом пока реализации сервера отложим и напишем небольшой клиент, для того что мы спокойно могли продолжать разрабатывать сервер.

Создадим новый проект (консольное приложения). В файле проекта также допишем строчки


QT       += network 
CONFIG += c++11 
	

Создаем новый класс Connection и наследуемся от Qobject. В данном классе мы реализуем логику подключения на сервер. В данном классе создади один публичный метод connectToServer который будет подключатся к нашему серверу.

Также необходимо создать поле, которое будет в себе хранить сокет, и соединить сигналами которые поступают от него со слотами, которые необходимо определить в данном классе.

Таким образом заголовок нашего класса выглядит следующим образом:


class Connection : public QObject
{
    Q_OBJECT
public:
    explicit Connection(QObject *parent = 0);

    void connectToServer();
private:
    QSslSocket *sslsocket;
signals:


public slots:
    void readyRead();
    void encrypted();
    void connected();
    void disconnected();
    void socketError(QAbstractSocket::SocketError error);
    void socketSslErrors(const QList &list);
};
	

Самым важным методом является  connectToServer, в нем необходимо подключится к серверу, указав при этом сертификат, который сгенерировали при помощи openssl. Обратите внимание что, я подключаюсь к серверу, расположенному по адресу 127.0.0.1, соответственно в сертификате я должен указать   в поле Common Name адрес 127.0.0.1.



void Connection::connectToServer()
{
    this->sslsocket->connectToHostEncrypted("127.0.0.1",1234);

    this->sslsocket->addCaCertificates("key.pem");

    if (this->sslsocket->waitForEncrypted()) {
        qDebug()<<"connected";
        this->sslsocket->write("hello");
        if(this->sslsocket->waitForBytesWritten()) {
            qDebug()<<"send msg";
        } else {
            qDebug()<sslsocket->errorString();
        }
    } else {
        qDebug()<<"error:"<sslsocket->errorString();
    }
}
	

На сервере в слоте получения сигнала что есть данные для чтения пропишем вывод о том на какой сокет пришел сигнал и выводим сами данные.


Connection* connection = new Connection();
    connection->connectToServer();

Что же пришло запустить на сервер и поробывать подключится к нему с нашего клиента. В клиенте в функции main укажем:

Запускаем сервер и запускаем клиент
Сервер:

qtsslServer_connect_client

Клиент:

qt_ssl_client_connect_to_server

Как видно из изображений,мы успешно установили соединения и послали нашему серверу «hello». Если мы запустим еще один клиент то увидим новое соединения и новое «hello», только уже на другом дескрипторе сокета. 

couple_connections_on_qtsslServer

Комментарий (0)

Войдите с помощью соцсетей:
или
введите свои данные: