基于QT5、C/S(客户端/服务器)架构的MiniQQ项目开发

基于QT5、C/S(客户端/服务器)架构的MiniQQ项目开发

1.系统概要设计
MiniQQ的体系结构(如图1.1所示),包括服务器端和客户端;服务器端又包括验证用户登录、保存用户信息、显示在线用户、转发用户信息、保存聊天记录、转发文本消息;客户端包括用户登录,文字聊天、截屏传输、文件传输、软键盘、视频聊天、查看聊天记录等功能模块。

图1.1

2.详细设计

2.1 验证用户登录基本思想

首先,服务端收到客户端发送过来的账号密码,其会和数据库中的数据进行比较,如果id和pd比较都相等,那么服务器端将会使icode等于0.,然后发送到客户端,如果id和pd其中有一个不相等或者都不相等,那么就会继续比较数据库中的senderid与id是否相同,如果相同就令mark=1,接着再令icode=0,然后发送到客户端;如果不相同就令mark=0,然后将接收到的id和pd插入数据库,然后令icode=2,然后发送到客户端;然后结束。

case
NewParticipant:

    {

       
in>>sport>>senderID>>pd>>senderipAddress;

        int regiser;

        regiser=0;

   /********judge id and pwd*******/

        QSqlDatabase
db1=QSqlDatabase::database("connection1");//连接数据库1

        QSqlQuery query1(db1);
        QString
select_all_data="select * from QQchat";
   
query1.prepare(select_all_data);

        query1.exec();

        while(query1.next())

        {

           
//qDebug()<<"running";

           
qDebug()<<query1.value("id").toString()<<query1.value("pwd").toString();

           
if(senderID==query1.value("id").toString())

                regiser=1;

           
if(senderID==query1.value("id").toString()&&pd==query1.value("pwd").toString())

            {

               
//QMessageBox::about(NULL,"about","login success!");

               
//qDebug()<<sport;

               
IPID_LIST.create_List(senderID,senderipAddress,sport);

               
newParticipant(senderID,senderipAddress,sport);

                icode=1;

               
sendMessage(NewParticipant,sport,senderID,senderipAddress);

                for(int
i=0;i<IPID_LIST.length_List();i++)

                {

                   
IPID_LIST.next_List();
           
//qDebug()<<"sendrunning";
            
sendMessage(getuser,10000,IPID_LIST.output_id(),senderipAddress);//send
old to new

                   
//qDebug()<<sport<<IPID_LIST.output_id()<<senderipAddress;

                   
if(senderID!=IPID_LIST.output_id())

                   
sendMessage(getuser,10000,senderID,IPID_LIST.output_ip());//send new to
old

                   
//qDebug()<<IPID_LIST.output_port()<<senderID<<IPID_LIST.output_ip();

                    else

                        continue;

                }

                break;

            }
         }

        if(regiser==0)

            icode=2;

        if(icode==0)

        {

           
//QMessageBox::warning(NULL,"warning","login
filed!");

           
sendMessage(NewParticipant,sport,senderID,senderipAddress);

 

        }

        if(icode==2)

        {

           
IPID_LIST.create_List(senderID,senderipAddress,sport);

           
newParticipant(senderID,senderipAddress,sport);

           
sendMessage(NewParticipant,sport,senderID,senderipAddress);

            for(int
i=0;i<IPID_LIST.length_List();i++)

            {

                IPID_LIST.next_List();

               
//qDebug()<<"sendrunning";

 

               
sendMessage(getuser,10000,IPID_LIST.output_id(),senderipAddress);//send
old to new

               
//qDebug()<<sport<<IPID_LIST.output_id()<<senderipAddress;

               
if(senderID!=IPID_LIST.output_id())

               
sendMessage(getuser,10000,senderID,IPID_LIST.output_ip());//send new to
old

               
//qDebug()<<IPID_LIST.output_port()<<senderID<<IPID_LIST.output_ip();

                else

                    continue;

            }

        }

        /********judge id and pwd*******/
       break;
   }

2.2 记录用户信息的基本思想

因为客户端登录的机器不断改变,IP地址不是固定的,所以客户端每次登录的时候,服务端都会记录当前客户端的信息。服务端采用建立链表的方式来记录当前客户端信息。客户端登录成功以后,服务器会把客户端的账号信息、IP地址信息、对应的端口号信息加入到链表中记录下来

下面是链表建立核心代码:

链表的节点结构

CID是登录用户账号信息

CIP是登录用户IP地址

Thisport是登录用户的端口号

typedef struct node

{

    QString CID;

    QString CIP;

    qint16
thisport;

    node *next;

}ND;

建立的链表类

Head头指针

Tail尾指针

Search查询指针

NDcount当前节点数目

class List

{

public:

    List();

    ~List();

    void
create_List(QString senderID,QString ipAddress,qint16 sport);

    int
length_List();

    void
delete_List(QString senderID);

    QString
output_ip();

    QString
output_ip1();

    QString next_List();

    QString
output_id();

    qint16
output_port();

 

private:

    ND* Head;

    ND* Tail;

    ND* Search;

    int NDcount;

    QSqlDatabase
db2;

};

当服务器启动时,对建立IPID_LIST链表初始化。NDcount记录在线用户个数。

List::List()

{

    NDcount=0;

    Head=new
node;

   
Head->next=NULL;

    Search=Head;

    Tail=Head;

}

create_List()当有用户加入时,创建一个节点,记录客户端的IP和端口号。

    void List::create_List(QString senderID,QString

ipAddress,qint16 sport)

{
 ND *s;
s=new node;

   
s->CID=senderID;

   
s->CIP=ipAddress;

   
s->thisport=sport;

   
s->next=NULL;

   
Tail->next=s;

    Tail=s;

    NDcount++;

}

length_List()用来输出在线人数。

int List::length_List()
    {
        return
    NDcount;
    }

delete_List()当有用户离开时删除该节点。Search指针是一个私有成员,用来查询节点,当search指针指向需要删除的节点,就把该指针指向头结点`。

void List::delete_List(QString
senderID)

{

    ND *p,*q;

    p=Head;

    q=Head->next;

    while(q!=NULL)

    {

        if(q->CID==senderID)

        {

            if(Search==q)

                Search=Head;

            if(q==Tail)

                Tail=p;

            p->next=q->next;

            delete q;

            NDcount--;

            break;

        }
           p=p->next;

            q=q->next;
   }

}

next_List()用来输出该节点的下一个节点ID信息。

    QString List::next_List()

{

Search=Search->next;

    if(Search==NULL)

    {
Search=Head->next;
    }

    return
Search->CID;
}

output_ip()用来输出searc指针指向当前节点的IP。

QString List::output_ip()

{

    return
Search->CIP;

}

List::~List()

{

    ND *p;

    p=Head;

   
while(p!=NULL)

    {

        delete
p;    
p=p->next;

    }

}

output_id()用来输出search

指针指向当前节点的ID信息

QString List::output_id()

{
    return
Search->CID;

}

outp

ut_port()用来输出search指针指向当前节点的端口信息

qint16 List::output_port()

{

    return
Search->thisport;

}

由于代码较多,下面只给出思想,不给出代码,需要源代码的话到最后的链接下载。

2.2显示在线用户思想

服务端记录用户登录信息后,会把该用户的信息显示在登录界面上,方便管理员查看

2.3用户退出基本思想

在客户端退出的时候,会给服务器发送一个退出数据包,服务器将记录的客户端信息从链表中删除,然后把该用户的退出信息转发给其他的在线用户,其他用户收到退出数据包后,会在box界面中删除该用户的ID号。

2.4转发用户信息基本思想

采用UDP进行转发信息。在用户登录成功以后,用户要从服务器上获取所有的其他在线用户,以便与其进行通信。服务器会把所有的在线用户发送给新加入用户,并且把新加入用户的信息发送给所有的在线用户。

2.5保存聊天记录基本思想

首先,服务端收到客户端的查看聊天记录请求,接着服务器端根据请求方的id在数据库中查找聊天记录,接着将聊天记录发送到客户端。

2.6转发文本消息基本思想

采用UDP进行数据的转发。客户端会把所有要发送的文本消息发送给服务端,服务端对该消息保存到数据库中并转发给目标主机。源主机发送的数据包中包含有源ID,源IP,目的ID和文本信息。服务端接收到该数据包后根据目的ID查询链表,获取目的ID的IP,然后对该文本消息进行转发。

2.7用户登录基本思想

采用UDP进行发送登录信息。用户在登录界面输入服务器IP,用户名和密码,然后把含有用户名和密码的数据包发送给服务端,服务端得到用户名和密码后进行判断,用户名是否存在,如果不存在就注册。如果存在就进行判断密码是否正确,如果不正确则返回数据包中不允许登录,反之允许登录到下一个界面。

2.8 文字聊天基本思想

采用UDP进行数据传输。客户端从widget界面中获取文本信息,从box界面中获取目的ID,然后对数据进行发送。源主机发送的数据包中包含有源ID,源IP,目的ID和文本信息。

2.9 截屏传输基本思想

首先需要截取下整个屏幕,再通过qt中的橡皮筋标记下需要截取的图片,再将需要截取的图片保存到一个Qpixmap类型的变量中,之后显示在在客户端上。发送方点击发送图片,会将图片转换成Qstring类型的数据,通过udp传输给接收方。接收方收到之后将Qstring转换成图片显示在自己的客户端上。

2.10文件传输的基本思想

首先接收端需要开启监听端口。其次在发送端需要从本机中获取文件,把文件转化为QString类型的数据。从文件中获取文件总大小、文件名长度、文件名组成首部,发送给接收端,其次再把文件的剩余数据发给接收端。接收端在接收到首部之后就获取到了文件的总大小、文件名长度和文件名,接着把文件的数据部分写入文件,然后就在已经编译好的miniqq文件夹中创建了此文件,打开文件看数据是否有所丢失。

2.11软键盘设计基本思想

使用qt中的button控件,每一个控件上都有对应的字母标志,点击对应的按钮会把字母显示到上方的edittext控件里,一个控件调整字母大小写,一个退格控件,点击确定按钮会把edittext控件里文本信息传输到对应的聊天界面中。

2.12查看聊天记录基本思想
注意,视频部分需要安装OpenCV,不然会无法编译

聊天记录在发送文本信息的时候,服务器转发时保存在数据库中。所以要查看聊天记录必须向服务器发送请求,然后服务器向请求的客户端发送聊天记录数据。

2.13视频聊天基本思想

采用UDP传输数据,客户端先向服务端请求接收方的IP,然后通过UDP直接进行视频传输。

以下为功能部分截图:

  1. 登录身份认证
    在这里插入图片描述
  2. 文字聊天功能
    在这里插入图片描述
  3. 文件传输功能
    在这里插入图片描述
    在这里插入图片描述
  4. 截图传输
    在这里插入图片描述
  5. 保存聊天记录
    在这里插入图片描述
  6. 软键盘
    在这里插入图片描述

源码下载:(https://download.csdn.net/download/qq_42161686/10897928)
注:源码包括已经编译好的在Linux下的可执行文件,以及源代码。

  • 5
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值