关于添加好友,过程如下:
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的时候是要转发给对方的。如果这里没有对方的名字,就不知道怎么转发,不知道转发给谁,所以对方的名字也要写进去