mysql ,C++,QT 聊天项目

目录

协议部分

                1.protoch.h

                2.protocl.cpp

客户端

        头文件 

                1.clicent.h

                2.online_user.h

                3.private_chat.h

                4.search_user.h

                5.user_operate.h

        源文件

                1.clicent.cpp

                2.online_user.cpp

                3.private_chat.cpp

                4.search_user.cpp

                5.user_operate.cpp

                6.main.cpp

        qt设计师界面

                1.clicent.ui

                2.online_user.ui

                3.private_chat.ui

                4.search_user.ui

                5.user_operate.ui

服务器

        头文件

                1.mytcpserver.h

                2.mytcpsocket.h

                3.opedb.h

                4.tcpservice.h

        源文件

                1.mytcpserver.cpp

                2.mytcpsocket.cpp

                3.opedb.cpp

                4.tcpservice.cpp

                5.main.cpp

mysql数据库部分

                1.userinfo

                2.friendinfo

效果展示


协议部分

也就是应用层协议,需要区分你发送的信息是要干什么,客户端和服务器都要有

                1.protoch.h

#ifndef PROTOCOL_H
#define PROTOCOL_H

#include<stdlib.h>
#include<string.h>
#include<unistd.h>

typedef unsigned int uint;

//注册------------------------------------------------
#define ENROLL_OK "enroll ok"
#define ENROLL_FAILED "enroll failed : name exists"
//登录------------------------------------------------
#define LOGIN_OK "LOGIN ok"
#define LOGIN_FAILED "LOGIN failed : you are relogin or (name or pwd) error"
//查询在线用户-----------------------------------------
#define ONLINE "you search person is online"
#define OFFLINE "you search person is offline"
#define NO_PEOPLE "you search person is not exist"
//添加好友-------------------------------------------
#define UNKONW_ERROR "unknow ERROR"
#define EXIST_FRIEND "friend exist"
#define ADD_FRIEND_OFFLINE  "the user is offline"
#define ADD_FRIEND_NO_EXIST "the user is not exist"
//删除好友-------------------------------------------
#define DELETE_SUCCESS "delete friend success"
#define DELETE_FALURE "delete friend falure"



enum ENUM_MSG_TYPE
{
    ENUM_MSG_TYPE_MIN = 0,

    ENUM_MSG_TYPE_ENROLL_REQUEST,           //注册请求  //c
    ENUM_MSG_TYPE_ENROLL_RESPOND,           //注册回复  //s

    ENUM_MSG_TYPE_LOGIN_REQUEST,            //登录请求  //c
    ENUM_MSG_TYPE_LOGIN_RESPOND,            //登录回复  //s

    ENUM_MSG_TYPE_ALL_ONLINE_REQUEST,       //查询在线用户请求  //c
    ENUM_MSG_TYPE_ALL_ONLINE_RESPOND,       //查询在线用户回复  //s

    ENUM_MSG_TYPE_SEARCH_USER_REQUEST,      //查找用户请求  //c
    ENUM_MSG_TYPE_SEARCH_USER_RESPOND,      //查找用户回复  //s

    ENUM_MSG_TYPE_ADD_FRIEND_REQUEST,       //加好友请求  //c s
    ENUM_MSG_TYPE_ADD_FRIEND_RESPOND,       //加好友回复  //s c

    ENUM_MSG_TYPE_ADD_FRIEND_AGREE,         //同意添加好友  //c
    ENUM_MSG_TYPE_ADD_FRIEND_REFUSE,        //拒绝添加好友  //s

    ENUM_MSG_TYPE_FLUSH_FRIENDS_REQUEST,    //刷新在线好友请求  //c
    ENUM_MSG_TYPE_FLUSH_FRIENDS_RESPOND,    //刷新在线好友回复  //s

    ENUM_MSG_TYPE_FLUSH_ALLFRIENDS_REQUEST, //刷新所有好友请求  //c
    ENUM_MSG_TYPE_FLUSH_ALLFRIENDS_RESPOND, //刷新所有好友回复  //s

    ENUM_MSG_TYPE_delete_FRIENDS_REQUEST,   //删除好友请求  //c
    ENUM_MSG_TYPE_delete_FRIENDS_RESPOND,   //删除好友回复  //s

    ENUM_MSG_TYPE_PRIVATE_CHAT_REQUEST,     //私聊好友请求  //c
    ENUM_MSG_TYPE_PRIVATE_CHAT_RESPOND,     //私聊好友回复  //s

    //ENUM_MSG_TYPE_REQUEST,        //注册请求  //c
    //ENUM_MSG_TYPE_RESPOND,        //注册回复  //s

    ENUM_MSG_TYPE_MAX = 0x00ffffff
};

struct PDU
{
    uint uiPDULen;  //总的协议数据大小
    uint uiMsgType; //消息类型
    uint uiMsgLen;  //实际消息长度
    char cadata[64];//文件名
    int caMsg[];    //实际消息
};

PDU *mkPDU(uint uiMsgLen);//动态申请空间。





#endif // PROTOCOL_H

                2.protocl.cpp

#include"protocol.h"

PDU *mkPDU(uint uiMsgLen)
{
    uint uiPDULen = sizeof(PDU)+uiMsgLen;
    PDU *pdu = (PDU*)malloc(uiPDULen);
    if(NULL==pdu)
    {
        exit(EXIT_FAILURE);
    }
    memset(pdu,0,uiPDULen);
    pdu->uiMsgLen = uiMsgLen;
    pdu->uiPDULen = uiPDULen;
    return pdu;
}

客户端

        头文件 

                1.clicent.h

#ifndef CLICENT_H
#define CLICENT_H

#include <QMainWindow>
#include <QTcpSocket>
#include <protocol.h>
QT_BEGIN_NAMESPACE
namespace Ui { class clicent; }
QT_END_NAMESPACE

class clicent : public QMainWindow
{
    Q_OBJECT

public:
    clicent(QWidget *parent = nullptr);
    ~clicent();

    static clicent &getInstance();
    void loadconfig();  //加载配置
    QTcpSocket &gettcpsocket(){return m_tcpsocket;}
    QString login_name();
    void add_friend(const QString addname);

public slots:
    void showconnect();
    void recvsmsg();

private slots:
    void on_pushButton_login_clicked();

    void on_pushButton_enroll_clicked();

private:
    Ui::clicent *ui;

    //------------------------------------------------------
    QString m_strIP;    //字符类型,存放ip地址
    quint16 us_port;    //无符号16位整形

    QTcpSocket m_tcpsocket;//一个用与tcp连接的对象,连接服务器,和服务器进行交换。
    QString m_strloginname;//登录时所用的用户名


};
#endif // CLICENT_H

                2.online_user.h

#ifndef ONLINE_USER_H
#define ONLINE_USER_H

#include <QDockWidget>
#include "protocol.h"
namespace Ui {
class online_user;
}

class online_user : public QDockWidget
{
    Q_OBJECT

public:
    explicit online_user(QWidget *parent = nullptr);
    ~online_user();
    static online_user &getInstance();
    void show_online_user(PDU*pdu);


private slots:
    void on_pushButton_flush_clicked();

    void on_pushButton_add_friends_clicked();

private:
    Ui::online_user *ui;
};

#endif // ONLINE_USER_H

                3.private_chat.h

#ifndef PRIVATE_CHAT_H
#define PRIVATE_CHAT_H

#include <QDockWidget>
#include <protocol.h>
namespace Ui {
class private_chat;
}

class private_chat : public QDockWidget
{
    Q_OBJECT

public:
    explicit private_chat(QWidget *parent = nullptr);
    ~private_chat();
    static private_chat &getInstance();
    QString retname(){return chatname;}
    void set_chatname(QString chatname);
    QString ret_chatname();
    void updata_msg(PDU *pdu);
private slots:
    void on_pushButton_send_msg_clicked();

private:
    Ui::private_chat *ui;
    QString chatname;
};

#endif // PRIVATE_CHAT_H

                4.search_user.h

#ifndef SEARCH_USER_H
#define SEARCH_USER_H

#include <QDockWidget>

namespace Ui {
class search_user;
}

class search_user : public QDockWidget
{
    Q_OBJECT

public:
    explicit search_user(QWidget *parent = nullptr);
    ~search_user();
    static search_user &getInstance();
private slots:
    void on_pushButton_search_clicked();

    void on_pushButton_adduser_clicked();

private:
    Ui::search_user *ui;
};

#endif // SEARCH_USER_H

                5.user_operate.h

#ifndef USER_OPERATE_H
#define USER_OPERATE_H

#include <QMainWindow>
#include <online_user.h>
#include "search_user.h"
#include "private_chat.h"
namespace Ui {
class User_operate;
}

class User_operate : public QMainWindow
{
    Q_OBJECT

public:
    explicit User_operate(QWidget *parent = nullptr);
    ~User_operate();

    static User_operate&getInstance();
    void show_friends(PDU* pdu);
    void show_ALLfriend(PDU *pdu);
    static void flush_friend();
    static void flush_ALLfriend();
    private_chat* search_chat_windows(QString chatname);
    QList<private_chat*> retQlistchat_windows(){return chat_windows;}
private slots:
    void on_pushButton_onlineuser_clicked();

    void on_pushButton_searchuser_clicked();

    void on_pushButton_flush_friends_clicked();

    void on_pushButton_deletefriend_clicked();

    void on_pushButton_private_chat_clicked();

private:
    Ui::User_operate *ui;
    online_user *onuser;
    search_user *seuser;
    QList<private_chat*> chat_windows;
};

#endif // USER_OPERATE_H

        源文件

                1.clicent.cpp

#include "clicent.h"
#include "ui_clicent.h"
#include "user_operate.h"
#include "protocol.h"
#include "private_chat.h"

#include <QFile>
#include <QMessageBox>
QString allname;
clicent::clicent(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::clicent)
{
    ui->setupUi(this);

    //加载配置文件--------------------
    loadconfig();
    //连接服务器---------------------------------------
    connect(&m_tcpsocket,SIGNAL(connected()),this,SLOT(showconnect())); //发送数据
    connect(&m_tcpsocket,SIGNAL(readyRead()),this,SLOT(recvsmsg()));    //接受数据
    m_tcpsocket.connectToHost(QHostAddress(m_strIP), us_port);          //连接服务器
}

clicent::~clicent()
{
    delete ui;
}

clicent &clicent::getInstance()
{
    static clicent instance;
    return instance;
}

void clicent::loadconfig()
{

    QFile file(":/client.config");                      //选取文件路径
    if(file.open(QIODevice::ReadOnly))                  //bool类型,只读打开,成功返true
    {
        QByteArray badata = file.readAll();             //以字节形似读取所有数据出来
        QString strdata = badata.toStdString().c_str(); //将badata转化为字符串类型
        file.close();                                   //关闭文件

        strdata.replace("\r\n"," ");                    //将/r/n替换成空格
        QStringList strlist = strdata.split(" ");       //以空格为准,将strdata里的数据进行分割后放入strlist

        m_strIP = strlist.at(0);
        us_port = strlist.at(1).toUShort();
    }
    else
    {
        QMessageBox::critical(this,"open config","open config failed");
    }


}

QString clicent::login_name()
{
    return allname;
}

void clicent::add_friend(const QString addname)
{
    if(addname == allname)
    {
        QMessageBox::information(this,allname,"don't add yourself");
        return;
    }
    //创建pdu包-----------------------------------
    PDU *pdu = mkPDU(0);
    pdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_REQUEST;
    QString myname = allname;
    memcpy(pdu->cadata,addname.toStdString().c_str(),addname.size());
    memcpy(pdu->cadata+32,myname.toStdString().c_str(),myname.size());
    //发送包---------------------------------------------------
    m_tcpsocket.write((char*)pdu,pdu->uiPDULen);
    //----------------------------------------------------------
    free(pdu);
    pdu = NULL;
}

void clicent::showconnect()
{
    QMessageBox::information(this,"提示","连接服务器成功");
}

void clicent::recvsmsg()
{
    QString name = allname;
    //读取收到的pdu中的数据-------------------------------------------
    uint uiPDULen = 0;
    m_tcpsocket.read((char*)&uiPDULen,sizeof(uint));
    uint uiMsgLen = uiPDULen - sizeof(PDU);
    PDU *pdu = mkPDU(uiMsgLen);
    m_tcpsocket.read((char*)pdu+sizeof(uint),uiPDULen-sizeof(uint));
    //对数据类型进行判断以确定要执行什么--------------------------------
    switch(pdu->uiMsgType)
    {
    case ENUM_MSG_TYPE_ENROLL_RESPOND:          //注册回复类型
    {
        if(strcmp(pdu->cadata,ENROLL_OK) == 0)
        {
            QMessageBox::information(this,name,"注册成功");
        }
        else if(strcmp(pdu->cadata,ENROLL_FAILED) == 0)
        {
            QMessageBox::warning(this,name,"注册失败,重命名");
        }
        else
        {
            QMessageBox::warning(this,name,"注册失败,请联系管理员");
        }
        break;
    }
    case ENUM_MSG_TYPE_LOGIN_RESPOND:           //登录回复类型
    {
        if(strcmp(pdu->cadata,LOGIN_OK) == 0)
        {
            QMessageBox::information(this,name,"登录成功");
            User_operate::getInstance().show();    //显示登录后的界面

            this->hide();
        }
        else if(strcmp(pdu->cadata,LOGIN_FAILED) == 0)
        {
            QMessageBox::warning(this,name,"登录失败,you are relogin or (name or pwd) error");
        }
        else
        {
            QMessageBox::warning(this,name,"登录失败,请联系管理员");
        }
        break;
    }
    case ENUM_MSG_TYPE_ALL_ONLINE_RESPOND:      //在线用户类型
    {
        online_user::getInstance().show_online_user(pdu);
        break;
    }
    case ENUM_MSG_TYPE_SEARCH_USER_RESPOND:     //查找用户类型
    {
        //QString name = click_logined::getInstance().retname();
        if(strcmp(pdu->cadata,ONLINE) == 0)
        {
            QString data = QString("'%1'在线").arg("用户");
            QMessageBox::information(this,name,data);
        }
        else if(strcmp(pdu->cadata,OFFLINE) == 0)
        {
            QString data = QString("'%1'不在线").arg("用户");
            QMessageBox::information(this,name,data);
        }
        else
        {
            QString data = QString("'%1'不存在").arg("用户");
            QMessageBox::information(this,name,data);
        }
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:      //添加好友请求
    {
        char myname[32] = {'\0'};
        strncpy(myname,pdu->cadata+32,32);
        QString data = QString("'%1' want to become your friend").arg(myname);
        int ret = QMessageBox::information(this,name,data,QMessageBox::Yes,QMessageBox::No);
        //产生一个回复的respdu
        PDU *respdu = mkPDU(0);
        memcpy(respdu->cadata,pdu->cadata,64);
        if(ret == QMessageBox::Yes)
        {
            respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_AGREE;

        }
        else
        {
            respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_REFUSE;

        }
        //发送respdu-------------------------------------
        m_tcpsocket.write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_RESPOND:      //添加好友回复
    {
        QMessageBox::information(this,name,pdu->cadata);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_AGREE:        //添加好友同意
    {
        char addname[32] = {'\0'};
        strncpy(addname,pdu->cadata,32);
        QString data = QString("%1 agree your request").arg(addname);
        QMessageBox::information(this,name,data);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_REFUSE:       //添加好友拒绝
    {
        char addname[32] = {'\0'};
        strncpy(addname,pdu->cadata,32);
        QString data = QString("%1 refuse your request").arg(addname);
        QMessageBox::information(this,name,data);
        break;
    }
    case ENUM_MSG_TYPE_FLUSH_FRIENDS_RESPOND:   //刷新好友回复
    {
        User_operate::getInstance().show_friends(pdu);
        break;
    }
    case ENUM_MSG_TYPE_FLUSH_ALLFRIENDS_RESPOND://刷新所有好友
    {
        User_operate::getInstance().show_ALLfriend(pdu);
        break;
    }
    case ENUM_MSG_TYPE_delete_FRIENDS_RESPOND:  //删除好友回复
    {
        if(strcmp(pdu->cadata,DELETE_SUCCESS) == 0)
        {
            QMessageBox::information(this,name,DELETE_SUCCESS);
            User_operate::flush_friend();
            User_operate::flush_ALLfriend();
        }
        else
        {
            QMessageBox::information(this,name,DELETE_FALURE);
        }
        break;
    }
    case ENUM_MSG_TYPE_PRIVATE_CHAT_REQUEST:    //私聊好友发送
    {
        //qDebug()<<"收到";
        char chat_name[32] = {'\0'};
        char myname[32] = {'\0'};
        strncpy(chat_name,pdu->cadata+32,32);
        strncpy(myname,pdu->cadata,32);
        //qDebug()<<chat_name<<myname;
        private_chat * chat_window = User_operate::getInstance().search_chat_windows(chat_name);
        if(chat_window == NULL)
        {
            chat_window = new private_chat;
            chat_window->set_chatname(chat_name);
            QString data = QString("'%1 chat with '%2' by this windows").arg(clicent::getInstance().login_name()).arg(chat_name);

            chat_window->setWindowTitle(data);
            User_operate::getInstance().retQlistchat_windows().append(chat_window);
            //qDebug()<<"chat_window append ok";
        }
        chat_window->updata_msg(pdu);
        User_operate::getInstance().addDockWidget(Qt::BottomDockWidgetArea,chat_window);
        chat_window->show();
        break;
    }
    default:
    {
        break;
    }
    }
    free(pdu);
    pdu = NULL;

}

void clicent::on_pushButton_login_clicked()
{
    QString strname = ui->lineEdit_username->text();
    allname = ui->lineEdit_username->text();
    QString strpwd = ui->lineEdit_userpassward->text();
    if(!strname.isEmpty()&&!strpwd.isEmpty())
    {
        //pdu构建----------------------------------------------
        PDU *pdu = mkPDU(0);
        pdu->uiMsgType = ENUM_MSG_TYPE_LOGIN_REQUEST;               //消息类型为登录类型
        strncpy(pdu->cadata,strname.toStdString().c_str(),32);      //获取账户
        strncpy(pdu->cadata+32,strpwd.toStdString().c_str(),32);    //获取密码
        //socket发送-------------------------------------------
        m_tcpsocket.write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu = NULL;
    }
    else
    {
        QMessageBox::critical(this,"提示","登录失败:用户名和密码不能为空");
    }
}

void clicent::on_pushButton_enroll_clicked()
{
    QString strname = ui->lineEdit_username->text();
    QString strpwd = ui->lineEdit_userpassward->text();
    if(!strname.isEmpty()&&!strpwd.isEmpty())
    {
        //pdu构建----------------------------------------------
        PDU *pdu = mkPDU(0);
        pdu->uiMsgType = ENUM_MSG_TYPE_ENROLL_REQUEST;              //消息类型为注册类型
        strncpy(pdu->cadata,strname.toStdString().c_str(),32);      //获取注册账户
        strncpy(pdu->cadata+32,strpwd.toStdString().c_str(),32);    //获取注册密码
        //socket发送-------------------------------------------
        m_tcpsocket.write((char*)pdu,pdu->uiPDULen);
        free(pdu);
        pdu = NULL;
    }
    else
    {
        QMessageBox::critical(this,"提示","注册失败:用户名和密码不能为空");
    }
}

                2.online_user.cpp

#include "online_user.h"
#include "ui_online_user.h"
#include "clicent.h"
#include "user_operate.h"
#include "QMessageBox"
online_user::online_user(QWidget *parent) :
    QDockWidget(parent),
    ui(new Ui::online_user)
{
    ui->setupUi(this);
}

online_user::~online_user()
{
    delete ui;
}

online_user &online_user::getInstance()
{
    static online_user instance;
    return instance;
}

void online_user::show_online_user(PDU *pdu)
{
    ui->listWidget_onlineuser->clear();//清空数据
    if(pdu == NULL)
    {
        QMessageBox::critical(this,clicent::getInstance().login_name(),"有问题");
        return;
    }
    else
    {
        //提取数据----------------------
        uint uisize = pdu->uiMsgLen/32;     //获取数据个数
        char catmp[32];
        for(uint i = 0;i<uisize;i++)
        {
            memcpy(catmp,(char*)(pdu->caMsg)+i*32,32);
            ui->listWidget_onlineuser->addItem(catmp);
        }
    }
    //显示界面------------------------------------
    User_operate::getInstance().addDockWidget(Qt::RightDockWidgetArea,this);
    this->show();
}

void online_user::on_pushButton_flush_clicked()
{
    //发送pdu,请求在线用户---------------------------
    PDU *pdu = mkPDU(0);
    pdu->uiMsgType = ENUM_MSG_TYPE_ALL_ONLINE_REQUEST;
    clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
    //释放pdu---------------------------------------
    free(pdu);
    pdu = NULL;
    //收到数据包后在显示,否则数据不会出来-------------------
}

void online_user::on_pushButton_add_friends_clicked()
{
    //发送添加好友包-----------------------------------
    QString addname = ui->listWidget_onlineuser->currentItem()->text();
    clicent::getInstance().add_friend(addname);
}

                3.private_chat.cpp

#include "private_chat.h"
#include "ui_private_chat.h"
#include "clicent.h"
#include "protocol.h"

#include "QMessageBox"
#include "stdlib.h"
private_chat::private_chat(QWidget *parent) :
    QDockWidget(parent),
    ui(new Ui::private_chat)
{
    ui->setupUi(this);
}

private_chat::~private_chat()
{
    delete ui;
}

private_chat &private_chat::getInstance()
{
    static private_chat instance;
    return instance;
}

void private_chat::set_chatname(QString chatname)
{
    this->chatname = chatname;
}

QString private_chat::ret_chatname()
{
    return chatname;
}

void private_chat::updata_msg(PDU *pdu)
{
    if(pdu == NULL )
    {
        return;
    }
    else
    {
        char sendname[32] = {'\0'};
        memcpy(sendname,pdu->cadata+32,32);
        QString strmsg = QString("%1 say: %2").arg(sendname).arg((char*)pdu->caMsg);
        ui->textEdit_show_msg->append(strmsg);
    }

}

void private_chat::on_pushButton_send_msg_clicked()
{
    //获取双方名字-----------------------
    char chat_name[32];
    char myname[32];
    strncpy(chat_name,retname().toStdString().c_str(),32);
    strncpy(myname,clicent::getInstance().login_name().toStdString().c_str(),32);
    //qDebgu()<<myname<<"发送pdu"<<chat_name;
    //获取要发送的信息--------------------
    QString strdata = ui->lineEdit_msg_input->text();
    if(strdata.isEmpty())
    {
        QMessageBox::information(this,clicent::getInstance().login_name(),"send message is NULL");
        return ;
    }
    else
    {
        //构建pdu---------------------------
        PDU *pdu = mkPDU(strdata.size()+1);
        pdu->uiMsgType = ENUM_MSG_TYPE_PRIVATE_CHAT_REQUEST;
        strncpy(pdu->cadata,chat_name,32);
        strncpy(pdu->cadata+32,myname,32);
        //qDebug()<<pdu->cadata+32<<"发送pdu"<<pdu->cadata;
        strncpy((char*)pdu->caMsg,strdata.toStdString().c_str(),strdata.size()+1);
        //发送pdu---------------------------
        clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
        updata_msg(pdu);
        //释放pdu---------------------------
        free(pdu);
        pdu = NULL;
    }

}

                4.search_user.cpp

#include "search_user.h"
#include "ui_search_user.h"
#include "protocol.h"
#include "QMessageBox"
#include "clicent.h"

search_user::search_user(QWidget *parent) :
    QDockWidget(parent),
    ui(new Ui::search_user)
{
    ui->setupUi(this);
}

search_user::~search_user()
{
    delete ui;
}

search_user &search_user::getInstance()
{
    static search_user instance;
    return instance;
}

void search_user::on_pushButton_search_clicked()
{
    QString searchname = ui->lineEdit_searchname->text();
    //构建pdu包---------------------------------
    if(!searchname.isEmpty())
    {
        //生成pdu包---------------------------------------
        PDU* pdu = mkPDU(0);
        pdu->uiMsgType = ENUM_MSG_TYPE_SEARCH_USER_REQUEST;
        strncpy(pdu->cadata,searchname.toStdString().c_str(),32);
        clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
        //释放pdu---------------------------------------
        free(pdu);
        pdu = NULL;
    }
    else if (searchname.isEmpty())
    {
        QMessageBox::critical(this,"提示","name不能为空");
    }
    else
    {
        return;
    }
}

void search_user::on_pushButton_adduser_clicked()
{
    //发送添加好友包-----------------------------------
    QString addname = ui->lineEdit_searchname->text();
    clicent::getInstance().add_friend(addname);

}

                5.user_operate.cpp

#include "user_operate.h"
#include "ui_user_operate.h"
#include "online_user.h"
#include "protocol.h"
#include "clicent.h"
#include "private_chat.h"

#include "QInputDialog"
#include "QMessageBox"
User_operate::User_operate(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::User_operate)
{
    ui->setupUi(this);
    //---------------------------------------------
    onuser = new online_user;
    seuser = new search_user;
    flush_ALLfriend();
    flush_friend();
    setWindowTitle(clicent::getInstance().login_name());
}

User_operate::~User_operate()
{
    delete ui;
}

User_operate &User_operate::getInstance()
{
    static User_operate instance;
    return instance;
}

void User_operate::show_friends(PDU *pdu)
{
    ui->listWidget_friends->clear();
    if(pdu == NULL)
    {
        return;
    }
    else
    {
        //提取数据----------------------
        uint uisize = pdu->uiMsgLen/32;     //获取数据个数
        char catmp[32];

        for(uint i = 0;i<uisize;i++)
        {
            memcpy(catmp,(char*)(pdu->caMsg)+i*32,32);
            ui->listWidget_friends->addItem(catmp);
        }
    }
    //显示界面------------------------------------
    this->show();
}

void User_operate::show_ALLfriend(PDU *pdu)
{
    ui->listWidget_Allfriend->clear();
    if(pdu == NULL)
    {
        return;
    }
    else
    {
        //提取数据----------------------
        uint uisize = pdu->uiMsgLen/32;     //获取数据个数
        char catmp[32];

        for(uint i = 0;i<uisize;i++)
        {
            memcpy(catmp,(char*)(pdu->caMsg)+i*32,32);
            ui->listWidget_Allfriend->addItem(catmp);
        }
    }
    //显示界面------------------------------------
    this->show();
}

void User_operate::flush_friend()
{
    //发送pdu,请求在线好友---------------------------
    PDU *pdu = mkPDU(0);
    pdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FRIENDS_REQUEST;
    QString strname = clicent::getInstance().login_name();
    memcpy(pdu->cadata,strname.toStdString().c_str(),strname.size());
    clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
    //释放pdu---------------------------------------
    free(pdu);
    pdu = NULL;
}

void User_operate::flush_ALLfriend()
{
    //发送pdu,请求所有好友---------------------------
    PDU *pdu = mkPDU(0);
    pdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_ALLFRIENDS_REQUEST;
    QString strname = clicent::getInstance().login_name();
    memcpy(pdu->cadata,strname.toStdString().c_str(),strname.size());
    clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
    //释放pdu---------------------------------------
    free(pdu);
    pdu = NULL;
}

private_chat *User_operate::search_chat_windows(QString chatname)
{
    for(int i = 0;i<chat_windows.size();i++)
    {
        chat_windows.at(i)->ret_chatname();
        //qDebug()<<"search_chat_windows;"<<chat_windows.at(i)->ret_chatname();
        if(chatname == chat_windows.at(i)->ret_chatname())
        {
            return chat_windows.at(i);
        }
    }
    return NULL;
}

void User_operate::on_pushButton_onlineuser_clicked()
{
    //发送pdu,请求在线用户---------------------------
    PDU *pdu = mkPDU(0);
    pdu->uiMsgType = ENUM_MSG_TYPE_ALL_ONLINE_REQUEST;
    clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
    //释放pdu---------------------------------------
    free(pdu);
    pdu = NULL;
    //收到数据包后在显示,否则数据不会出来-------------------
}

void User_operate::on_pushButton_searchuser_clicked()
{
    //显示dockwidget--------------------------------
    addDockWidget(Qt::RightDockWidgetArea,seuser);
    seuser->show();
}

void User_operate::on_pushButton_flush_friends_clicked()
{
    flush_friend();
    flush_ALLfriend();
}

void User_operate::on_pushButton_deletefriend_clicked()
{
    char defriend[32] = {'\0'};
    char myname[32] = {'\0'};
    if(ui->listWidget_friends->currentItem() == NULL)
    {
        return;
    }
    strncpy(defriend,ui->listWidget_friends->currentItem()->text().toStdString().c_str(),32);
    strncpy(myname,clicent::getInstance().login_name().toStdString().c_str(),32);

    QString data = QString("Are you sure to delete '%1'").arg(defriend);
    int ret = QMessageBox::information(this,clicent::getInstance().login_name(),data,QMessageBox::Yes,QMessageBox::No);
    if(ret == QMessageBox::Yes)
    {
        //创建pdu包-----------------------
        PDU* pdu = mkPDU(0);
        pdu->uiMsgType = ENUM_MSG_TYPE_delete_FRIENDS_REQUEST;
        memcpy(pdu->cadata,defriend,32);
        memcpy(pdu->cadata+32,myname,32);
        //发送pdu包------------------------
        clicent::getInstance().gettcpsocket().write((char*)pdu,pdu->uiPDULen);
        //释放pdu---------------------------------------
        free(pdu);
        pdu = NULL;
    }
    return;

}

void User_operate::on_pushButton_private_chat_clicked()
{
    //获取私聊名字--------------------
    if(ui->listWidget_friends->currentItem()==NULL)
    {
        QMessageBox::information(this,clicent::getInstance().login_name(),"please choose your chat name");
        return;
    }
    QString chatname = ui->listWidget_friends->currentItem()->text();
    private_chat *chat_window = search_chat_windows(chatname);
    if(chat_window == NULL)
    {
        chat_window = new private_chat;
        chat_window->set_chatname(chatname);
        QString data = QString("'%1 chat with '%2' by this windows").arg(clicent::getInstance().login_name()).arg(chatname);

        chat_window->setWindowTitle(data);
        chat_windows.append(chat_window);
        //qDebug()<<"chat_window append ok";
    }
    //显示私聊页面-------------------- 
    addDockWidget(Qt::BottomDockWidgetArea,chat_window);
    chat_window->show();
}

                6.main.cpp

#include "clicent.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //User_operate w;
    clicent w;
    w.show();
    return a.exec();
}

        qt设计师界面

                1.clicent.ui

 

                2.online_user.ui

 

                3.private_chat.ui

 

                4.search_user.ui

                5.user_operate.ui

服务器

 

        头文件

                1.mytcpserver.h

#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H


#include"mytcpsocket.h"
#include <QTcpServer>
#include<QList>
#include"protocol.h"

class myTcpServer : public QTcpServer
{
    Q_OBJECT
public:
    myTcpServer();

    static myTcpServer & getInstance(); //C++单例程模式

    void incomingConnection(qintptr socketDescriptor);
    void resend(char *addname,PDU*respdu);


public slots:
    void deletesocket(MyTcpSocket *mysocket);


private:
    QList<MyTcpSocket*> m_tcpsocketlist;

};

#endif // MYTCPSERVER_H

                2.mytcpsocket.h

#ifndef MYTCPSOCKET_H
#define MYTCPSOCKET_H

#include <QTcpSocket>



class MyTcpSocket : public QTcpSocket
{
    Q_OBJECT
public:
    explicit MyTcpSocket(QObject *parent = nullptr);
    QString getname(){return m_strname;}

signals:
    void offline(MyTcpSocket *mysocket);



public slots:
    void recvMsg();
    void clientoffline();


private:
    QString m_strname;

};

#endif // MYTCPSOCKET_H

                3.opedb.h

#ifndef OPEDB_H
#define OPEDB_H

#include <QObject>
#include <QSqlDatabase> //连接数据库
#include <QSqlQuery>    //查询数据库
#include<QStringList>
class OpeDB : public QObject
{
    Q_OBJECT
public:
    explicit OpeDB(QObject *parent = nullptr);
    ~OpeDB(){m_db.close();}
    //-------------------------------------------------------
    static OpeDB& getInstance();
    void init();

    bool handle_enroll(const char*name,const char*pwd);                     //注册函数
    bool handle_login(const char*name,const char*pwd);                      //登录函数
    void handle_offline(const char*name);                                   //下线操作函数
    QStringList handle_alline();                                            //查找在线用户函数
    int handle_searchuser(const char*name);                                 //搜索某一用户操作函数
    int handle_addfriend(const char *addname,const char *myname);           //添加好友操作函数
    bool handle_addfriend_if_agreeconst (char *addname,const char *myname); //同意添加好友请求
    QStringList handle_flush_friends(const char*name);                      //刷新好友列表
    QStringList handle_flush_ALLfriends(const char*name);                   //刷新所有好友列表
    bool handle_delefriend(char *delefriend,const char *myname);            //删除好友操作

signals:

public slots:

private:
    QSqlDatabase m_db;

};

#endif // OPEDB_H

                4.tcpservice.h

#ifndef TCPSERVICE_H
#define TCPSERVICE_H

#include <QWidget>
#include <QFile>
//#include <QTcpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class tcpservice; }
QT_END_NAMESPACE

class tcpservice : public QWidget
{
    Q_OBJECT

public:
    tcpservice(QWidget *parent = nullptr);
    ~tcpservice();
    //------------------------------------------------------
    void loadconfig();

private:
    Ui::tcpservice *ui;
    //------------------------------------------------------
    QString m_strIP;    //字符类型,存放ip地址
    quint16 us_port;    //无符号16位整形
};
#endif // TCPSERVICE_H

        源文件

                1.mytcpserver.cpp

#include "mytcpserver.h"
#include "QDebug"
myTcpServer::myTcpServer()
{

}

myTcpServer &myTcpServer::getInstance()
{
    static myTcpServer instance;
    return instance;
}

//针对父类的虚函数重写,每当监听到新的连接时就会自动调用此函数。
void myTcpServer::incomingConnection(qintptr socketDescriptor)
{
    //qDebug()<<"new client connect";
    MyTcpSocket *ptcpsocket = new MyTcpSocket;
    ptcpsocket->setSocketDescriptor(socketDescriptor);
    m_tcpsocketlist.append(ptcpsocket);
    connect(ptcpsocket,SIGNAL(offline(MyTcpSocket*)),this,SLOT(deletesocket(MyTcpSocket *)));
}

void myTcpServer::resend(char *addname, PDU *respdu)
{
    if(addname == NULL || respdu == NULL)
    {
        return ;
    }
    for(int i = 0;i<m_tcpsocketlist.size();i++)
    {
        if(m_tcpsocketlist.at(i)->getname()==addname)
        {
            m_tcpsocketlist.at(i)->write((char*)respdu,respdu->uiPDULen);
            break;
        }
    }

}

void myTcpServer::deletesocket(MyTcpSocket *mysocket)
{
    //-------------------------------------------------
    //for(int i = 0;i<m_tcpsocketlist.size();i++)
    //{
    //    qDebug()<<m_tcpsocketlist.at(i)->getname();
    //}

    //迭代器遍历----------------------------------------
    //个人认为这里可以改进
    QList<MyTcpSocket*>::Iterator iter = m_tcpsocketlist.begin();
    for(;iter!=m_tcpsocketlist.end();iter++)
    {
        if(mysocket == *iter)
        {
            delete *iter;
            *iter = NULL;
            m_tcpsocketlist.erase(iter);
            //qDebug()<<"a clicent off line";
            break;
        }
    }
    //----------------------------------------------------


}

                2.mytcpsocket.cpp

#include "mytcpsocket.h"
#include "mytcpserver.h"
#include "protocol.h"
#include"opedb.h"
#include<QDebug>
#include<QStringList>
MyTcpSocket::MyTcpSocket(QObject *parent)
    : QTcpSocket{parent}
{
    connect(this,SIGNAL(readyRead()),this,SLOT(recvMsg()));
    connect(this,SIGNAL(disconnected()),this,SLOT(clientoffline()));
}

//对收到的数据进行处理
void MyTcpSocket::recvMsg()
{
    //qDebug()<< this->bytesAvailable();              //当前的this是一个QTCPSOCKET类。
    uint uiPDULen = 0;
    this->read((char*)&uiPDULen,sizeof(uint));
    uint uiMsgLen = uiPDULen - sizeof(PDU);
    PDU *pdu = mkPDU(uiMsgLen);
    this->read((char*)pdu+sizeof(uint),uiPDULen-sizeof(uint));
    //类型处理--------------------------------------------------------
    switch(pdu->uiMsgType)
    {
    case ENUM_MSG_TYPE_ENROLL_REQUEST:          //注册消息类型
    {
        //获取名字密码--------------------------------------------
        char caname[32] = {'\0'};
        char capwd[32] = {'\0'};
        strncpy(caname,pdu->cadata,32);
        strncpy(capwd,pdu->cadata+32,32);
        //-------------------------------------------------------
        PDU*respdu = mkPDU(0);                                  //注册回复消息
        respdu->uiMsgType = ENUM_MSG_TYPE_ENROLL_RESPOND;       //注册回复类型

        bool ret = OpeDB::getInstance().handle_enroll(caname,capwd);
        if(ret)    //对是否成功添加到数据库进行判断
        {
            strcpy(respdu->cadata,ENROLL_OK);
        }
        else
        {
            strcpy(respdu->cadata,ENROLL_FAILED);
        }
        //回复消息-------------------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_LOGIN_REQUEST:           //登录消息类型
    {
        //获取名字密码--------------------------------------------
        char caname[32] = {'\0'};
        char capwd[32] = {'\0'};
        strncpy(caname,pdu->cadata,32);
        strncpy(capwd,pdu->cadata+32,32);
        //登录回复消息---------------------------------------------
        PDU*respdu = mkPDU(0);
        respdu->uiMsgType = ENUM_MSG_TYPE_LOGIN_RESPOND;       //登录回复类型

        bool ret = OpeDB::getInstance().handle_login(caname,capwd);
        if(ret)    //对是否成功添加到数据库进行判断
        {
            strcpy(respdu->cadata,LOGIN_OK);
            m_strname = caname;
        }
        else
        {
            strcpy(respdu->cadata,LOGIN_FAILED);
        }
        //回复消息-------------------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;

    }
    case ENUM_MSG_TYPE_ALL_ONLINE_REQUEST:      //在线用户类型
    {
        //获取所有在线用户信息------------------------------
        QStringList res = OpeDB::getInstance().handle_alline();
        //制作PDU包----------------------------------------
        uint uimsglen = res.size()*32;
        PDU *respdu = mkPDU(uimsglen);
        respdu->uiMsgType = ENUM_MSG_TYPE_ALL_ONLINE_RESPOND;
        for(int i = 0;i<res.size();i++)
        {
            memcpy((char*)(respdu->caMsg)+i*32,
                   res.at(i).toStdString().c_str(),
                   res.at(i).size());
        }
        //回复消息-----------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_SEARCH_USER_REQUEST:     //搜索用户类型
    {
        char caname[32] = {'\0'};
        strncpy(caname,pdu->cadata,32);
        PDU *respdu = mkPDU(0);
        respdu->uiMsgType = ENUM_MSG_TYPE_SEARCH_USER_RESPOND;
        int ret = OpeDB::getInstance().handle_searchuser(caname);
        if(ret == 0)
        {

            strcpy(respdu->cadata,OFFLINE);
        }
        else if (ret == 1)
        {

            strcpy(respdu->cadata,ONLINE);
        }
        else
        {
            //QString data = QString("%1,is not searched").arg(caname);
            strcpy(respdu->cadata,NO_PEOPLE);
        }
        //回复消息-----------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_REQUEST:      //添加好友类型
    {
        char addname[32] = {'\0'};
        char myname[32] = {'\0'};
        strncpy(addname,pdu->cadata,32);
        strncpy(myname,pdu->cadata+32,32);
        int ret = OpeDB::getInstance().handle_addfriend(addname,myname);
        //构建respdu包
        PDU *respdu = mkPDU(0);
        respdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_RESPOND;
        if(ret != 1)
        {
            if(ret == 0)
            {
                strcpy(respdu->cadata,EXIST_FRIEND);
            }
            else if(ret == 2)
            {
                strcpy(respdu->cadata,ADD_FRIEND_OFFLINE);
            }
            else if(ret == 3)
            {
                strcpy(respdu->cadata,ADD_FRIEND_NO_EXIST);
            }
            else
            {
                strcpy(respdu->cadata,UNKONW_ERROR);
            }
            //回复消息-----------------------------------------
            this->write((char*)respdu,respdu->uiPDULen);
            free(respdu);
            respdu = NULL;
        }
        if(ret == 1)
        {
            //在线,发送添加好友请求-------------------------
            myTcpServer::getInstance().resend(addname,pdu);
        }
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_AGREE:        //添加好友同意
    {

        char addname[32] = {'\0'};
        char myname[32] = {'\0'};
        strncpy(addname,pdu->cadata,32);
        strncpy(myname,pdu->cadata+32,32);
        //还有一个数据库操作,将其添加为好友------------------------
        int ret = OpeDB::getInstance().handle_addfriend_if_agreeconst(addname,myname);
        if(ret != true)
        {
            pdu->uiMsgType = ENUM_MSG_TYPE_ADD_FRIEND_REFUSE;
        }


        //转发-------------------------------------------------
        myTcpServer::getInstance().resend(myname,pdu);
        break;
    }
    case ENUM_MSG_TYPE_ADD_FRIEND_REFUSE:       //添加好友拒绝
    {
        char myname[32] = {'\0'};
        strncpy(myname,pdu->cadata+32,32);
        //转发-------------------------------------------------
        myTcpServer::getInstance().resend(myname,pdu);
        break;
    }
    case ENUM_MSG_TYPE_FLUSH_FRIENDS_REQUEST:   //刷新好友请求
    {
        char strname[32];
        strncpy(strname,pdu->cadata,32);
        //获取所有在线用户信息------------------------------
        QStringList res = OpeDB::getInstance().handle_flush_friends(strname);
        //制作PDU包----------------------------------------
        uint uimsglen = res.size()*32;
        PDU *respdu = mkPDU(uimsglen);
        respdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_FRIENDS_RESPOND;
        for(int i = 0;i<res.size();i++)
        {
            memcpy((char*)(respdu->caMsg)+i*32,
                   res.at(i).toStdString().c_str(),
                   res.at(i).size());
        }
        //回复消息-----------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_FLUSH_ALLFRIENDS_REQUEST://刷新所有好友
    {
        char strname[32];
        strncpy(strname,pdu->cadata,32);
        //获取所有在线用户信息------------------------------
        QStringList res = OpeDB::getInstance().handle_flush_ALLfriends(strname);
        //制作PDU包----------------------------------------
        uint uimsglen = res.size()*32;
        PDU *respdu = mkPDU(uimsglen);
        respdu->uiMsgType = ENUM_MSG_TYPE_FLUSH_ALLFRIENDS_RESPOND;
        for(int i = 0;i<res.size();i++)
        {
            memcpy((char*)(respdu->caMsg)+i*32,
                   res.at(i).toStdString().c_str(),
                   res.at(i).size());
        }
        //回复消息-----------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_delete_FRIENDS_REQUEST:  //删除好友请求
    {
        char delname[32] = {'\0'};
        char myname[32] = {'\0'};
        strncpy(delname,pdu->cadata,32);
        strncpy(myname,pdu->cadata+32,32);
        //数据库删除操作--------------------------------
        bool ret = OpeDB::getInstance().handle_delefriend(delname,myname);
        //发送respdu包-------------------------------
        PDU *respdu = mkPDU(0);
        respdu->uiMsgType = ENUM_MSG_TYPE_delete_FRIENDS_RESPOND;
        if(ret == true)
        {
            strcpy(respdu->cadata,DELETE_SUCCESS);
        }
        else
        {
            strcpy(respdu->cadata,DELETE_FALURE);
        }
        //回复消息-----------------------------------------
        this->write((char*)respdu,respdu->uiPDULen);
        //释放respdu包-------------------------------
        free(respdu);
        respdu = NULL;
        break;
    }
    case ENUM_MSG_TYPE_PRIVATE_CHAT_REQUEST:    //发送私聊请求
    {
        char pcname[32] = {'\0'};
        memcpy(pcname,pdu->cadata,32);
        qDebug()<<pcname<<(char*)(pdu->cadata+32);
        myTcpServer::getInstance().resend(pcname,pdu);

        break;
    }

    default:
    {
        break;
    }
    }
    //---------------------------------------------------------------
    free(pdu);
    pdu = NULL;
}

void MyTcpSocket::clientoffline()
{
    //改数据库
    OpeDB::getInstance().handle_offline(m_strname.toStdString().c_str());
    //改socketlist

    emit offline(this);     //this指代当前socket

}

                3.opedb.cpp

#include "opedb.h"
#include<QMessageBox>
#include<QDebug>

OpeDB::OpeDB(QObject *parent)
    : QObject{parent}
{
    m_db = QSqlDatabase::addDatabase("QMYSQL");
}

OpeDB &OpeDB::getInstance()
{
    static OpeDB instance;
    return instance;
}

void OpeDB::init()
{
    m_db.setHostName("127.0.0.1");          //设置连接数据库的地此
    m_db.setPort(3306);
    m_db.setDatabaseName("my_online_disk"); //设置要操作的数据库
    m_db.setUserName("root");               //root用户
    m_db.setPassword("123456");             //密码

    if(!m_db.open())
    {
        QMessageBox::critical(NULL,"打开数据库","打开数据库失败");
    }
}

bool OpeDB::handle_enroll(const char *name, const char *pwd)
{

    if(!name||!pwd)
    {
        return false;
    }
    QString data = QString("insert into userinfo(name,passward) values(\'%1\',\'%2\')").arg(name).arg(pwd);
    QSqlQuery query;
    return query.exec(data);


}

bool OpeDB::handle_login(const char *name, const char *pwd)
{
    if(!name||!pwd)
    {
        return false;
    }
    QString data = QString("select * from userinfo where name = '%1' and passward = '%2' and online = 0 ").arg(name).arg(pwd);
    QSqlQuery query;
    query.exec(data);
    if(query.next())
    {
        data = QString("update userinfo set online = 1 where name = '%1' and passward = '%2' ").arg(name).arg(pwd);
        QSqlQuery query1;
        return query1.exec(data);
    }
    else
    {
        return false;
    }
}

void OpeDB::handle_offline(const char *name)
{
    if(!name)
    {
        qDebug()<<"name is null";
    }
    QString data = QString("update userinfo set online = 0 where name = '%1'").arg(name);
    QSqlQuery query;
    query.exec(data);

}

QStringList OpeDB::handle_alline()
{
    QString data = QString("select name from userinfo where online = 1");
    QSqlQuery query;
    query.exec(data);

    QStringList result;
    result.clear();
    while(query.next())
    {
        result.append(query.value(0).toString());
    }
    return result;
}

int OpeDB::handle_searchuser(const char *name)
{
    if(name == NULL)
    {
        return -1;
    }
    QString data = QString("select online from userinfo where name = '%1'").arg(name);
    QSqlQuery query;
    query.exec(data);
    if(query.next())
    {
        if(query.value(0).toInt())
        {
            return 1;   //在线
        }
        else
        {
            return 0;   //不在线
        }

    }
    return -1;
}

int OpeDB::handle_addfriend(const char *addname, const char *myname)
{
    if(addname == NULL || myname == NULL || myname == addname)
    {
        return -1;
    }
    QString data = QString("select * from friendinfo where "
                           "(id = (select id from userinfo where name = '%1') and "
                           "friendid = (select id from userinfo where name = '%2')) "
                           "or "
                           "(id = (select id from userinfo where name = '%3') and "
                           "friendid = (select id from userinfo where name = '%4'))").arg(addname).arg(myname).arg(myname).arg(addname);
    QSqlQuery query;
    query.exec(data);
    qDebug ()<< data;
    if(query.next())
    {
        return 0;//已经是好友了
    }
    else
    {
        int ret = handle_searchuser(addname);
        if(ret == 1)
        {
            return 1;//在线
        }
        else if (ret == 0)
        {
            return 2;//不在线
        }
        else
        {
            return 3;//不存在这个人
        }
    }


}

bool OpeDB::handle_addfriend_if_agreeconst(char *addname, const char *myname)
{
    if(addname == NULL || myname == NULL || myname == addname)
    {
        return false;
    }
    else
    {
        QString data = QString("insert into friendinfo values"
                               "((select id from userinfo where name = '%1'),(select id from userinfo where name = '%2')),"
                               "((select id from userinfo where name = '%3'),(select id from userinfo where name = '%4'))").arg(addname).arg(myname).arg(myname).arg(addname);
        QSqlQuery query;
        query.exec(data);
        return true;
    }
    return false;
}

QStringList OpeDB::handle_flush_friends(const char *name)
{
    QStringList strfriendlist;
    strfriendlist.clear();
    if(name == NULL)
    {
        return strfriendlist;
    }

    QString data = QString("select name from userinfo where (id) in "
                           "(select friendid from friendinfo where id = "
                           "(select id from userinfo where name = '%1')) and online = 1").arg(name);
    QSqlQuery query;
    query.exec(data);

    while(query.next())
    {
        strfriendlist.append(query.value(0).toString());
    }
    return strfriendlist;


}

QStringList OpeDB::handle_flush_ALLfriends(const char *name)
{
    QStringList strfriendlist;
    strfriendlist.clear();
    if(name == NULL)
    {
        return strfriendlist;
    }

    QString data = QString("select name from userinfo where (id) in "
                           "(select friendid from friendinfo where id = "
                           "(select id from userinfo where name = '%1'))").arg(name);
    QSqlQuery query;
    query.exec(data);

    while(query.next())
    {
        strfriendlist.append(query.value(0).toString());
    }
    return strfriendlist;
}

bool OpeDB::handle_delefriend(char *delefriend, const char *myname)
{
    if(delefriend == NULL || myname == NULL || myname == delefriend)
    {
        return false;
    }
    else
    {
        QString data = QString("delete from friendinfo where id = "
                               "(select id from userinfo where name = '%1') and "
                               "friendid = (select id from userinfo where name = '%2')").arg(myname).arg(delefriend);
        QSqlQuery query;
        bool reta = query.exec(data);
        data = QString("delete from friendinfo where id = "
                       "(select id from userinfo where name = '%1') and "
                       "friendid = (select id from userinfo where name = '%2')").arg(delefriend).arg(myname);
        bool retb = query.exec(data);
        if(reta && retb )
        {
            return true;
        }
    }
    return false;
}

                4.tcpservice.cpp

#include "tcpservice.h"
#include "ui_tcpservice.h"
#include "mytcpserver.h"
#include <QByteArray>
//#include <QDebug>
#include <QMessageBox>
#include <QHostAddress>

tcpservice::tcpservice(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::tcpservice)
{
    ui->setupUi(this);
    //---------------------------------------------
    loadconfig();

    myTcpServer::getInstance().listen(QHostAddress(m_strIP),us_port);

}

tcpservice::~tcpservice()
{
    delete ui;
}

void tcpservice::loadconfig()
{
    QFile file(":/service.config");                      //选取文件路径
    if(file.open(QIODevice::ReadOnly))                  //bool类型,只读打开,成功返true
    {
        QByteArray badata = file.readAll();             //以字节形似读取所有数据出来
        QString strdata = badata.toStdString().c_str(); //将badata转化为字符串类型
        file.close();                                   //关闭文件

        strdata.replace("\r\n"," ");                    //将/r/n替换成空格
        QStringList strlist = strdata.split(" ");       //以空格为准,将strdata里的数据进行分割后放入strlist

        m_strIP = strlist.at(0);
        us_port = strlist.at(1).toUShort();

    }
    else
    {
        QMessageBox::critical(this,"open config","open config failed");
    }
}

                5.main.cpp

#include "tcpservice.h"
#include "opedb.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    //------------------------------
    OpeDB::getInstance().init();



    //------------------------------
    tcpservice w;
    w.show();
    return a.exec();
}

mysql数据库部分

                1.userinfo

create table userInfo(
	id int primary key auto_increment,
    name varchar(32) unique,
    passward varchar(32),
    online int default 0
)comment'用户表';

                2.friendinfo

create table friendInfo(
	id int,
    friendid int,
    primary key(id, friendid)
)comment'好友表';

效果展示

                1.登录

                2.用户操作界面

                3.与好友聊天

                4.搜索

 

做的不是很完美,还有很多可以改进的地方,

后面有空会添加文件系统,上传文件。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱睡觉更爱学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值