网盘——添加好友

关于添加好友,过程如下:

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

相关推荐
九河云29 分钟前
AWS账号注册费用详解:新用户是否需要付费?
服务器·云计算·aws
Lary_Rock34 分钟前
RK3576 LINUX RKNN SDK 测试
linux·运维·服务器
幺零九零零1 小时前
【计算机网络】TCP协议面试常考(一)
服务器·tcp/ip·计算机网络
云飞云共享云桌面2 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
一坨阿亮4 小时前
Linux 使用中的问题
linux·运维
幺零九零零6 小时前
【C++】socket套接字编程
linux·服务器·网络·c++
wclass-zhengge6 小时前
Docker篇(Docker Compose)
运维·docker·容器
李启柱6 小时前
项目开发流程规范文档
运维·软件构建·个人开发·设计规范
free7 小时前
netstat中sendq/recvq用于排查发送端发送数据的问题
服务器
力姆泰克7 小时前
看电动缸是如何提高农机的自动化水平
大数据·运维·服务器·数据库·人工智能·自动化·1024程序员节