Автор: CbIHOK 15.6.2010, 7:11
Коллеги, столкнулся с какой-то проблемой при реализации простенького SMTP. Собственно протокол класса:
CODE
#ifndef SMTP_H
#define SMTP_H
#include <QThread>
#include <QTcpSocket>
class Smtp : public QThread
{
Q_OBJECT
friend class QScopedPointerDeleter<Smtp>;
private:
enum SmtpState{
Init,
Hello,
Login,
Password,
From,
Rcpt,
Data,
Body,
Quit,
Close
}m_state;
QString m_body;
bool m_status;
QString m_error_message;
QTcpSocket *m_socket;
QTextStream *m_stream;
QString readSocket();
void writeSocket(const QString & data);
static QByteArray encode64(const QString & secure_string);
protected:
explicit Smtp(const QString & message);
~Smtp();
void run();
inline bool getStatus() const
{
return m_status;
}
inline QString getErrorMessage() const
{
return m_error_message;
}
public:
static bool send(const QString & message, QString & error);
protected slots:
void onSocketData();
};
#endif // SMTP_H
и немного реализации
CODE
bool Smtp::send(const QString &message, QString &error)
{
Smtp smtp(message);
smtp.start();
smtp.wait();
error = smtp.getErrorMessage();
return smtp.getStatus();
}
void Smtp::run()
{
// if SMTP server requires secure connection
if (Settings::instance()->value(Settings::KeySmtpUseSsl).toBool())
{
// create new SSL socket
QSslSocket * socket = new QSslSocket(this);
m_socket = socket;
// assign socket data handler
connect(m_socket, SIGNAL(readyRead()), this, SLOT(onSocketData()));
// assign proxy object if needed
if (Settings::instance()->value(Settings::KeyUseProxy).toBool())
{
QNetworkProxy proxy(QNetworkProxy::HttpProxy,
Settings::instance()->value(Settings::KeyProxyHost).toString(),
Settings::instance()->value(Settings::KeyProxyPort).toUInt(),
Settings::instance()->value(Settings::KeyProxyLogin).toString(),
Settings::instance()->value(Settings::KeyProxyPassword).toString());
socket->setProxy(proxy);
}
// connect to SMTP server over SSL
socket->connectToHostEncrypted(Settings::instance()->value(Settings::KeySmtpHost).toString(),
Settings::instance()->value(Settings::KeySmtpPort).toUInt());
// wait for the connection
if (!socket->waitForEncrypted())
{
m_status = false;
m_error_message = socket->errorString();
return;
}
}
else // SMTP server doesn't require SSL connection
{
// create TCP socket
QTcpSocket * socket = new QTcpSocket(this);
m_socket = socket;
// assign socket data handler
connect(m_socket, SIGNAL(readyRead()), this, SLOT(onSocketData()));
// assign proxy object if needed
if (Settings::instance()->value(Settings::KeyUseProxy).toBool())
{
QNetworkProxy proxy(QNetworkProxy::HttpProxy,
Settings::instance()->value(Settings::KeyProxyHost).toString(),
Settings::instance()->value(Settings::KeyProxyPort).toUInt(),
Settings::instance()->value(Settings::KeyProxyLogin).toString(),
Settings::instance()->value(Settings::KeyProxyPassword).toString());
socket->setProxy(proxy);
}
// connect to SMTP server
socket->connectToHost(Settings::instance()->value(Settings::KeySmtpHost).toString(),
Settings::instance()->value(Settings::KeySmtpPort).toUInt());
// wait for connection
if (!socket->waitForConnected())
{
m_status = false;
m_error_message = socket->errorString();
return;
}
}
// create new text stream
m_stream = new QTextStream(m_socket);
// start event loop
m_status = (exec() == 0);
}
Т.е. интересует отсылка письма с заморозкой текущего трида. Код зависает после входа в EventLoop, слот onSocketData() не вызывается, хотя при реализации в рамках одного трида все Ok.
Автор: ViGOur 15.6.2010, 20:34
Цитата(CbIHOK @ 15.6.2010, 8:11)
Т.е. интересует отсылка письма с заморозкой текущего трида.
Не совсем понял, что ты имеешь ввиду...
А загвоздка думается мне в твоей функции:
bool Smtp::send(const QString &message, QString &error)
{
Smtp smtp(message);
smtp.start();
smtp.wait();
error = smtp.getErrorMessage();
return smtp.getStatus();
}
в ней ты создаешь объект Smtp, запускаешь поток (где он подготовливает все для нормальной работы с удаленным сервером), ждет пока он запустится, и возвращаешь статус соединения. А что потом? Выходишь из функции и объект
Smtp smtp(message); вне зоны видимости, а значит он уничтожается и для него вызывается деструктор со всеми вытекающими...
Для интереса можешь в этом убедиться примерно таким кодом:
Smtp::Smtp(...)
{
qDebug()<<"Создаем Smtp";
}
...
Smtp::~Smtp()
{
qDebug()<<"Уничтожаем Smtp";
}
...
qDebug()<<"Отправляем данные";
Smtp::send(...)
qDebug()<<"Отправили данные";