Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets > [Qt] Передача указателя this через сигнал


Автор: null56 17.12.2008, 16:28
В общем такая ситуация:
У меня в системе висит сервер, который cпит в ожидании клиентов, задача была сделать такую вещь, что после подключения клиента:
1) создавался бы объект SslSocket
2) запускался бы startServerEncryption
3) Сервер продолжал ожидать других клиентов, но с этим клиентом он продолжил бы работать, после прихода от него определенных сигналов (encryption или ошибки), в общем, чтобы не ждать уведомления о начале шифрования

Что я сделал
1) У меня существует класс MySslSocket(обертка), который содержит в себе переменную QSSlSocket и осуществляет манипуляции с ней
a) для перехвата событий от QSslSocket я создал слоты у класса MySslSocket и соединил их с нужными мне сигналами QSSlSocket
б) класс обертка MySslSocket перехватив в обработчике - слоте событие от QSslSocket генерит свой сигнал, который передает указатель на собственный объект:
Код

emit sendObject(this);

2) Основной класс TcpSocket находится в ожидании соединения и имеет слот, обработчик событий созданных объектов класса MySslSocket.... и очередь, которая хранит, на всякий случай указатели на объекты, чтобы они не просто так витали в памяти, для принудительного удаления
приведу упрощенный код функции incomingConnection
Код

void SslServer :: incomingConnection(int socketDescriptor)
{
    SslSocket * p_new_client_connection = new SslSocket(socketDescriptor, ssl_socket :: SOCK_SERVER, this);
    if (p_new_client_connection->isOk())
    {
        mUnenclyptedQuery.append(p_new_client_connection);
        qDebug("query count: %d", mUnenclyptedQuery.count());
        connect(p_new_client_connection, SIGNAL(sendObject(SslSocket *)), this, SLOT(newSocketSignal(SslSocket *)));
        p_new_client_connection->startEncrypt(mSslCertificate, mSslKey);
    }
       иначе удаляю объект
}


Собственно, для пришедшего соединения создается объект, хранящий сокет и, в случае успеха:
1) адрес созданного объекта кладется в очередь
2) соединяются сингал передачи объекта и обработчик события
3) Запуск enryption

Код обработки события
Код

void SslServer :: newSocketSignal(SslSocket * pSslSocket)
{
    qDebug("Emited socket descriptor: %d", pSslSocket->getSocket()->socketDescriptor());
    disconnect(pSslSocket, 0, this, 0);
    mUnenclyptedQuery.removeOne(pSslSocket);
    qDebug("query count: %d", mUnenclyptedQuery.count());
}


Собственно манипуляции, в зависимости от состояния сокета +  удаление указателя из очереди и отвязка сигнала, так как сокетом будет заниматься уже другой объект из другого потока

Вопрос к вам: если понятна моя идея, скажите, не слишком ли грязная реализация для этого получается? Код рабочий и идея, в принципе оправдана, но может быть сущестуеют менее извращенные способы решения этой задачи на qt

Заранее благодарен за помощь

Автор: Purple_Light 17.12.2008, 17:18
текст не осилил, но выскажусь, сильно не пинать.

Если тебе надо только получить информацию из объекта, то лучше передавать так называемый constant reference.

Например:
void object_operation_slot(const Object *obj);

Служебное слово const даст гарантию сохранности и неизменности объекта. Т.е. объект нельзя будет изменять и приэтом считывание с объекта будет быстре (кажись).

Автор: SABROG 17.12.2008, 17:25
Цитата(Purple_Light @  17.12.2008,  17:18 Найти цитируемый пост)
void object_operation_slot(const Object *obj);

А это разве не constant pointer ?

Автор: Purple_Light 17.12.2008, 17:32
Цитата(SABROG @ 17.12.2008,  17:25)
Цитата(Purple_Light @  17.12.2008,  17:18 Найти цитируемый пост)
void object_operation_slot(const Object *obj);

А это разве не constant pointer ?

да, может быть. У меня формулировка не точная.

update:
действительно 
const Object *obj - constant pointer
const Object &obj - constant reference

update 2:
если в интерфейсе функции указать значение как const, то основываять на этой информации компилятор попытается оптимизировать фукнцию для более быстрой работы. Но как он это делает, не могу найти. Буду рад если кто-нить кинет ссылку на инфу.

Автор: SABROG 17.12.2008, 18:50
Я чего-то не понимаю или тут как-раз так и делается ?

Код

         void SslServer::incomingConnection(int socketDescriptor)
         {
             QSslSocket *serverSocket = new QSslSocket;
             if (serverSocket->setSocketDescriptor(socketDescriptor)) {
                 connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready()));
                 serverSocket->startServerEncryption();
             } else {
                 delete serverSocket;
             }
         }


Т.е. если приходит сигнал encrypted, то соединение зашифровано. И если зашифрованное соединение установить не удалось, то пускается сигнал sslErrors, после которого соединение с клиентом прерывается и QSslSocket можно мочкануть через sender()'a. Просто довольно странно использовать подобное:

Код

emit sendObject(this);


Если sender() и так известен.

Автор: null56 17.12.2008, 22:00
Вот вот вот вот ... да, именно про связь я спрашивал, а то уж слишком сложно получается у меня

То есть из слота мы можем узнать указатель вызывающего объекта????
Через функцию sender()?

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

Спасибо, это и узнавал.... я просто это ручками пытался сделать, от незнания... 

Просто я не хотел терять адрес созданного сокета и завязывал на очередь + на сигнал дважды вызываемый с целью передать адрес


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)