邮件客户端:
一.初始化邮件主界面(在IMMailCtrl中定义)时,会在构造函数中初始化邮件通信控制类(在IMMailCtrl中定义),而IMMailCtrl类的构造函数会初始化IMTcpSocket(在IMTcpSocket中定义),并且连接IMTcpSocket和IMMailCtrl的信号与槽
IMMailWidget::IMMailWidget(const QString &myID, QWidget *parent)
: m_myID(myID), QWidget(parent)
{
m_mailCtrl = new IMMailCtrl(myID, this);
}
IMMailCtrl::IMMailCtrl(const QString & id, QObject *parent) :
m_myID(id), QObject(parent)
{
m_tcpSocket = new IMTcpSocket(this);
m_tcpSocket->setFlag(1);
m_tcpSocket->requestConnect();
connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(requestGetInMails()));
connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
}
二.当IMTcpSocket连接上时,调用IMMailCtrl的槽函数requestGetInMails,requestGetInMails函数通过IMTcpSocket将信息类型设置为GET_IN_MAIL 发送给服务器
void IMMailCtrl::requestGetInMails()
{
qDebug() << "request in mails";
if (NULL == m_tcpSocket)
return;
m_blockSize = 0;
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
// out.setVersion(QDataStream::Qt_4_8);
out << quint16(0) << int(GET_IN_MAILS) << m_myID;
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));
m_tcpSocket->write(block);
}
服务器端:
一.服务器用于控制客户端socket的类(在IMClientSocketCtrl中定义)的构造函数中连接了socket的信号和槽,当客户端的连接到达时,调用receiveMessage槽函数
IMClientSocketCtrl::IMClientSocketCtrl(QObject *parent)
:QTcpSocket(parent)
{
connect(this, &IMClientSocketCtrl::readyRead,
this, &IMClientSocketCtrl::receiveMessage);
connect(this, &IMClientSocketCtrl::disconnected,
this, &IMClientSocketCtrl::deleteScoket);
m_blockSize = 0;
m_save.m_clientSocket = this;
}
二.receiveMessage函数识别到GET_IN_MAILS消息类型,发出sendSignal信号
void IMClientSocketCtrl::receiveMessage()
{
QDataStream in(this);
//设置QDataStream的版本,这里先省略
if(m_blockSize == 0)
{
if(bytesAvailable() < (int)sizeof(quint16))
{
return;
}
in >> m_blockSize;
}
if(bytesAvailable() < m_blockSize)
{
return;
}
in >> m_save.m_requestKind;
qDebug() << "receive message: " << m_save.m_requestKind;
switch (m_save.m_requestKind)
{
case GET_IN_MAILS:
case GET_OUT_MAILS:
{
in >> m_save.m_myID;
m_save.m_socketID = m_save.m_myID;
m_save.m_socketID.append(MAIL_ADDRESS_FORMAT);
break;
}
}
emit sendSignal(m_save);
}
三.服务器类(在IMTcpServer中定义)捕获到这个信号,并调用sendMessage槽函数
void IMTcpServer::incomingConnection(int socketDescriptor)
{
//建立新连接,并连接相应的信号/槽
IMClientSocketCtrl *clientScoket = new IMClientSocketCtrl(this);
clientScoket->setSocketDescriptor(socketDescriptor);
connect(clientScoket, &IMClientSocketCtrl::sendSignal,
this, &IMTcpServer::sendMessage);
connect(clientScoket, &IMClientSocketCtrl::deleteSignal,
this, &IMTcpServer::clientDisconnected);
}
四.sendMessage函数识别到GET_IN_MAILS消息类型,通过数据库操作类(在IMDatabaseCtrl中定义)的searchInMails函数查询客户的收件箱记录,如果成功则返回消息类型GET_IN_MAILS_SUCCESS,并将收信箱信息存储在Vector中。然后向客户端发送查询到的收件箱信息以及消息类型
void IMTcpServer::sendMessage(const SaveTmpInformation &save)
{
m_save.m_requestKind = save.m_requestKind;
//根据save.request来处理各种信息
switch (m_save.m_requestKind) {
case GET_IN_MAILS:
{
m_save.m_myID = save.m_myID;
m_save.m_replyKind = m_database.searchInMails(m_save.m_myID, m_save.m_inMailsVec);
save.m_clientSocket->sendMessage(m_save);
if(GET_IN_MAILS_SUCCESS == m_save.m_replyKind)
{
QString mailAddress = save.m_myID;
mailAddress.append(MAIL_ADDRESS_FORMAT);
if(m_userMailMap.contains(mailAddress))
{
qDebug() << "have connected:" << mailAddress;
}
else
{
m_userMailMap.insert(mailAddress, save.m_clientSocket);
emit haveNewAddress(mailAddress);
}
}
break;
}
}
}
int IMDatabaseCtrl::searchInMails(const QString & id,
QVector<MailInformation> & mailsVec)
{
if (!createConnection())
{
return GET_IN_MAILS_FAIL;
}
//sql 事务
QSqlDatabase::database().transaction();
QSqlQuery query(*m_db);
query.prepare(SEARCH_IN_MAILS_IN_MAIL);
query.addBindValue(id);
query.addBindValue(MAIL_ADDRESS_FORMAT);
query.exec();
errorSQLOrder(query, "get-mails-search");
QSqlDatabase::database().commit();
if (!query.isActive())
{
m_db->close();
return GET_IN_MAILS_FAIL;
}
mailsVec.clear();
MailInformation mail;
while (query.next())
{
mail.m_mailID = query.value(0).toInt();
mail.m_senderAddress = query.value(1).toString();
// mail. = query.value(2).toString();
mail.m_receiverAddress = query.value(3).toString();
// mail. = query.value(4).toString();
mail.m_theme = query.value(5).toString();
mail.m_content = query.value(6).toString();
mail.m_dateTime = query.value(7).toDateTime();
mail.m_status = query.value(8).toInt();
mailsVec.push_back(mail);
}
return GET_IN_MAILS_SUCCESS;
}
邮件客户端:
一.客户端的邮件通信控制类(在IMMailCtrl中定义)中的客户端tcpsocket类(在IMTcoSocket中定义)接收到可以读的信号,调用槽函数readMessage函数进行处理
IMMailCtrl::IMMailCtrl(const QString & id, QObject *parent) :
m_myID(id), QObject(parent)
{
m_tcpSocket = new IMTcpSocket(this);
m_tcpSocket->setFlag(1);
m_tcpSocket->requestConnect();
connect(m_tcpSocket, SIGNAL(connected()), this, SLOT(requestGetInMails()));
connect(m_tcpSocket, SIGNAL(readyRead()), this, SLOT(readMessage()));
}
二.readMessage函数识别到消息类型为GET_IN_MAILS_SUCCESS,读取收信箱信息到Vector,发出getInMailsSuccess信号
void IMMailCtrl::readMessage()
{
if (NULL == m_tcpSocket)
return;
QDataStream in(m_tcpSocket);
if (m_blockSize == 0)
{
if (m_tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> m_blockSize;
}
if (m_tcpSocket->bytesAvailable() < m_blockSize)
return;
int type;
int len;
in >> type;
switch (type)
{
case GET_IN_MAILS_SUCCESS:
{
in >> len;
m_inMailsVec.clear();
m_inMailsVec.resize(len);
for(int i=0; i<len; i++)
{
in >> m_inMailsVec[i];
}
qDebug() << "in mails len: " << len;
emit getInMailsSuccess(m_inMailsVec);
break;
}
}
三.邮件主界面类(在IMMailWidget中定义)接收到信号,调用setInMailsWidget槽函数
void IMMailWidget::linkSignalWithSlot()
{
connect(m_mailCtrl, &IMMailCtrl::getInMailsSuccess,
this, &IMMailWidget::setInMailsWidget);
}
四.setInMailsWidget函数设置收信箱窗口,并调用邮件通信控制类(在IMMailCtrl中定义)的requestGetOutMails方法
void IMMailWidget::setInMailsWidget(const QVector<MailInformation> &inMailsVec)
{
int len = inMailsVec.size();
for(int i = 0; i < len; i ++)
{
addInMailButton(inMailsVec[i]);
}
m_mailCtrl->requestGetOutMails();
}
五.requestGetOutMails函数向服务器发送请求获取发件箱信息,接下来的过程与获取收信箱过程类似,就省略了。
void IMMailCtrl::requestGetInMails()
{
qDebug() << "request in mails";
if (NULL == m_tcpSocket)
return;
m_blockSize = 0;
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
// out.setVersion(QDataStream::Qt_4_8);
out << quint16(0) << int(GET_IN_MAILS) << m_myID;
out.device()->seek(0);
out << quint16(block.size() - sizeof(quint16));
m_tcpSocket->write(block);
}