关于添加好友,过程如下:
A、首先客户端A发送加好友的请求,发送的信息包括双方的用户名
B、当服务器收到请求之后,服务器将数据库中在线用户查找出来,如果客户端B已经是你的好友了,服务器告诉客户端A他已经是你的好友了。如果不是好友且客户端B在线则转发好友请求,不在线直接回复加好友失败。
C、客户端B接受请求信息并回复答复信息给服务器
D、如果同意被添加好友,则在数据库中添加好友信息。发送同意或者拒绝信息发送给客户端A。
QT代码实现
1、首先右击加好友按钮,并且转到槽clicked
2、在客户端还有服务器这里添加协议,保持客户端服务器协议一致
ENUM_MSG_TYPE_ADD_FRIEND_REQUEST, //添加好友请求ENUM_MSG_TYPE_ADD_FRIEND_RESPOND, //添加好友回复
3、获得左边的用户名
4、测试一下
void Online::on_addFriendpb_clicked()
{//发送当前点击的行,通过currentItem获得当前的文字信息QListWidgetItem *pItem = ui->online_lw->currentItem();qDebug()<< pItem->text();
}
可以看到,当我们添加22222和jack的时候,会打印出来这两个名字
5、获取pItem的用户名以及本机的用户名
A、要加的好友的用户名
QString strPerUsrName = pItem->text();
B、自己的用户名
在这里,直接在tcpclient里面定义一个,添加好友时候,自己的用户名
QString m_strLoginName;
使得再登录的时候,直接将登录的用户名传给他
m_strLoginName = strName;
C、定义一个共有的接口去获得他
QString loginName();
QString TcpClient::loginName()
{return m_strLoginName;
}
D、在tcpclient里面获得本机用户名
QString strLoginName = TcpClient::getinstance().loginName();
6、最后写你要添加谁,你是谁
void Online::on_addFriendpb_clicked()
{//发送当前点击的行,通过currentItem获得当前的文字信息QListWidgetItem *pItem = ui->online_lw->currentItem();//要加的好友的用户名QString strPerUsrName = pItem->text();//获得自己的名字QString strLoginName = TcpClient::getinstance().loginName();PDU *pdu = mkPDU(0);pdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_REQUEST;//你要添加谁?你是谁//获得数据的地址-要加的好友的用户名memcpy(pdu->caData, strPerUsrName.toStdString().c_str(), strPerUsrName.size());//登录的名字,往后放32个字节——自己的用户名memcpy(pdu->caData+32, strLoginName.toStdString().c_str(),strLoginName.size());
}
7、将信息发送出去
void Online::on_addFriendpb_clicked()
{//发送当前点击的行,通过currentItem获得当前的文字信息QListWidgetItem *pItem = ui->online_lw->currentItem();//要加的好友的用户名QString strPerUsrName = pItem->text();//获得自己的名字QString strLoginName = TcpClient::getinstance().loginName();PDU *pdu = mkPDU(0);pdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_REQUEST;//你要添加谁?你是谁//获得数据的地址-要加的好友的用户名memcpy(pdu->caData, strPerUsrName.toStdString().c_str(), strPerUsrName.size());//登录的名字,往后放32个字节——自己的用户名memcpy(pdu->caData+32, strLoginName.toStdString().c_str(),strLoginName.size());//将信息发送出去TcpClient::getinstance().getTcpSocket().write((char*)pdu,pdu->uiPDULen);free(pdu);pdu=NULL;
}
8、操作服务器
8.1、定义加好友的函数
//------------------------加好友--------------------------int handleAddFriend(const char *pername, const char *name);
8.2、在friend表里面添加数据
8.4、在服务器添加加好友的case
case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:{char caPerName[32] = {'\0'};char caName[32] ={'\0'};strncpy(caPerName, pdu->caData, 32);strncpy(caName, pdu->caData+32, 32);int ret = OperateDB::getInstance().handleAddFriend(caPerName,caName);PDU *respdu = NULL;if(-1==ret){respdu=mkPDU(0);respdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;strcpy(respdu->caData, UNKNOW_ERROR);//发送write((char*)respdu, respdu->uiPDULen);//释放空间free (respdu);respdu =NULL;}else if(0==ret){respdu=mkPDU(0);respdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;strcpy(respdu->caData, EXISTED_FRIEND);//发送write((char*)respdu, respdu->uiPDULen);//释放空间free (respdu);respdu =NULL;}else if(1==ret){//在线MyTcpServer::getInstance().reSend(caPerName,pdu);}else if(2==ret){respdu=mkPDU(0);respdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;strcpy(respdu->caData, ADD_FRIEND_OFFLINE);//发送write((char*)respdu, respdu->uiPDULen);//释放空间free (respdu);respdu =NULL;}else if(3==ret){respdu=mkPDU(0);respdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;strcpy(respdu->caData, ADD_FRIEND_NO_EXISTED);//发送write((char*)respdu, respdu->uiPDULen);//释放空间free (respdu);respdu =NULL;}break;}
int OperateDB::handleAddFriend(const char *pername, const char *name)
{//首先对形参的有效性做出判断if(NULL==pername||NULL==name){return -1;}//查看是否已经是自己的好友//我作为id,我的friendid里面有没有这个名字QString data = QString("select * from friend where (id=(select id from usrInfo where name = '\%1\') and friendId= (select id from usrInfo where name = '\%2\'))""or(id=(select id from usrInfo where name = '\%3\') and friendId=(select id from usrInfo where name = '\%4\'))").arg(pername).arg(name).arg(name).arg(pername);qDebug()<<data;QSqlQuery query;query.exec(data);if(query.next()){return 0;//双方已经是好友}else{data = QString("select online from usrInfo where name = \'%1\'").arg(pername);QSqlQuery query;query.exec(data);if(query.next()){//查看是否在线int ret = query.value(0).toUInt();if(1==ret){return 1;//不是好友 在线}else if(0==ret) {return 2;}}else {return 3;//对方不存在}}
}void OperateDB::handleAgreeAddfriend(const char *pername, const char *name)
{//首先对形参的有效性做出判断if(NULL==pername||NULL==name){return;}QString data = QString("insert into friend(id,friendId) values((select id from usrInfo where name=\'%1\'),(select id from usrInfo where name=\'%2\'))").arg(pername).arg(name);qDebug()<<data;QSqlQuery query;query.exec(data);
}
其中reSend的函数定义如下,这个是一个转发的函数,也就是将对方的名字传过来pername,pdu进行转发
void MyTcpServer::reSend(const char *pername, PDU *pdu)
{if(NULL==pername||NULL==pdu){return;}QString strName = pername;//遍历链表for(int i=0; i<m_tcpSocketList.size();i++){qDebug()<<m_tcpSocketList.at(i)->getName();if(strName==m_tcpSocketList.at(i)->getName()){m_tcpSocketList.at(i)->write((char*)pdu,pdu->uiPDULen);break;}}
}
8.5、添加好友的拒绝case
case ENUM_MSG_TYPE_ADD_FRIEND_REFUSE:{char caName[32] ={'\0'};strncpy(caName, pdu->caData+32, 32);MyTcpServer::getInstance().reSend(caName,pdu);break;}
8.6、对消息类型进行判断
在resend里面,使用的是原来的pdu,但是原来的pdu消息类型还是friend request,所以说接收方那边需要对这两种消息类型进行判断
A、添加好友回复
case ENUM_MSG_TYPE_ADD_FRIEND_RESPOND:{QMessageBox::information(this,"添加好友",pdu->caData);break;}
B、添加好友同意或者拒绝代码
case ENUM_MSG_TYPE_ADD_FRIEND_AGGREE:{char caPerName[32] = {'\0'};strncpy(caPerName, pdu->caData, 32);QMessageBox::information(this,"添加好友",QString("添加%1好友成功").arg(caPerName));break;}case ENUM_MSG_TYPE_ADD_FRIEND_REFUSE:{char caPerName[32] = {'\0'};strncpy(caPerName, pdu->caData, 32);QMessageBox::information(this,"添加好友",QString("添加%1好友失败").arg(caPerName));break;}
C、添加好友总的case
除了YES之外,其他的情况都属于是不同意
case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:{//同意添加好友还是不同意添加好友char caName[32]={'\0'};strncpy(caName,pdu->caData+32,32);int ret = QMessageBox::information(this,"添加好友",QString("%1 what to add you as friend?").arg(caName),QMessageBox::Yes,QMessageBox::No);PDU *respdu =mkPDU(0);//将对方的名字添加进来memcpy(respdu->caData,pdu->caData,64);if(QMessageBox::Yes==ret){//同意添加这个好友respdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_AGGREE;}else{//不同意添加这个好友respdu->uiMsgType=ENUM_MSG_TYPE_ADD_FRIEND_REFUSE;}m_tcpSocket.write((char*)respdu,respdu->uiPDULen);free(respdu);respdu=NULL;break;}
在这里只是将自己名字发送过去了,对方的名字也是需要发送过去的,服务器收到pdu的时候是要转发给对方的。如果这里没有对方的名字,就不知道怎么转发,不知道转发给谁,所以对方的名字也要写进去