网盘系统(2) 连接服务器,搭建服务器

客户端TCPSocket链接服务器 ,连接成功时服务器返回connected信号 弹出相应窗口(showConnect())

//链接服务器
    connect(&m_tcpSocket,&QTcpSocket::connected,[=](){
        this->showConnect();
    });

    m_tcpSocket.connectToHost(m_strIP,m_usPort);
 m_tcpSocket.connectToHost(m_strIP,m_usPort);

        这行代码是实际发起TCP连接请求的。它告诉m_tcpSocket对象尝试连接到指定的IP地址和端口。这个操作是异步的,意味着connectToHost函数会立即返回,而实际的连接过程会在后台进行。当连接成功时,m_tcpSocket会发射connected()信号。

搭建服务器:创建TcpServer文件

加载配置文件:TcpServer.cpp

        与在搭建客户端(TcpClient)加载资源文件的过程一致,打开文件,读取IP.PROT。

创建MyTcpServer.h继承QTcpServer,使用MyTcpServer创建的对象监听客户端的连接申请,

void incomingConnection()在客户端申请连接服务器自动调用

      MyTcpServer创建的对象监听客户端的连接申请:MyTcpServer::getInstance().listen(IP,PROT)

#include "mytcpserver.h"
#include <QDebug>

MyTcpServer::MyTcpServer(QObject *parent)
    : QTcpServer{parent}
{}

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

void MyTcpServer::incomingConnection(qintptr handle)
{
    qDebug()<<"new client connected";
}

客户端通过TcpSocket数据传入到PDU协议中的caMsg发送

服务器通过TcpSocket接受PDU中的数据,收到的信息写到数据库中,通过OpeDB.h文件进行实现。

服务器接收到消息的具体操作:

        1.客户端与数据库相互链接:

        m_db=QSqlDatabase::addDatabase("QSQLITE");//添加SQLite数据库连接

void OpeDB::init()
{
    m_db.setHostName("localhost");//连接数据库
    m_db.setDatabaseName("D:/SQLite3/TcpServer/cloud.db");//操作的数据库名称
    if(m_db.open())
    {
        //查询数据库
        QSqlQuery query;
        query.exec("select * from usrInfo");
        while(query.next())//遍历结果集,按行读取
        {
            QString data=QString("%1,%2,%3").arg(query.value(0).toString()).arg(query.value(1).toString()).arg(query.value(2).toString());
            qDebug()<<data;
        }
        qDebug()<<"数据库打开成功";

    }
    else
    {
        qDebug()<<"数据库打开失败";
        //QString title=QString("打开数据库");
        //QString mes=QString("数据库打开失败");
        //QMessageBox::critical(this,title,mes);
    }

}

2.使用socket读取从客户端传来的PDU的信息;

(1)先读取总的信息长度;

(2)再创建PDU,按照设置的PDU格式读取其他的信息;

//使用Socket读取从客户端传来的PDU的信息
    qDebug()<<this->bytesAvailable();
    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));//读取除了第一项数据总长度之外,PDU中其他的数据

(3)判断接收消息的类型进而进行不同的后续操作,此时接收的为注册申请,将用户信息写入数据库,写入操作如下:

            char caName[32]={'\0'};
            char caPwd[32]={'\0'};
            strncpy(caName,pdu->caData,32);
            strncpy(caPwd,pdu->caData+32,32);
            //将pdu信息写入数据库
            bool ret=OpeDB::getInstance().handleRegist(caName,caPwd);
bool OpeDB::handleRegist(const char *name, const char *pwd)
{
    if(name==nullptr || pwd==nullptr)
    {
        qDebug()<<"name==nullptr || pwd==nullptr false";
        return false;
    }
    QString data=QString("insert into usrInfo(name,pwd) values(\'%1\',\'%2\')").arg(name).arg(pwd);//在数据库的用户表中插入信息
    qDebug()<<data;
    QSqlQuery query;
    return query.exec(data);//在数据库中查询信息是否存在--数据是否插入成功
}

(4)数据写入成功后,返还给客户端 申请回复 的消息,将消息放入PDU中并由Socket进行发送write

            PDU *resPDU=mkPDU(0);//将回复信息放到resPDU的caData中
            if(ret)
            {
                //在数据库中写入信息成功,服务器回复客户端加入成功
                resPDU->uiMsgType=ENUM_MSG_TYPE_REGIST_RESPONE;
                strcpy(resPDU->caData,REGIST_OK);
            }
            else
            {
                QString str="regist false";
                strcpy(resPDU->caData,REGIST_FAILED);
            }
            //使用socket将存储的信息通过PDU发给客户端
            write((char*)resPDU,pdu->uiPDULen);
            freePDU(resPDU);
            resPDU=nullptr;

resvMsg具体代码

void MyTcpSocket::recvMsg()
{
    //使用Socket读取从客户端传来的PDU的信息
    qDebug()<<this->bytesAvailable();
    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));//读取除了第一项数据总长度之外,PDU中其他的数据

    //判断接收的数据类型
    switch (pdu->uiMsgType) {
        case ENUM_MSG_TYPE_REGIST_REQUEST://注册申请
        {
            char caName[32]={'\0'};
            char caPwd[32]={'\0'};
            strncpy(caName,pdu->caData,32);
            strncpy(caPwd,pdu->caData+32,32);
            //将pdu信息写入数据库
            bool ret=OpeDB::getInstance().handleRegist(caName,caPwd);

            PDU *resPDU=mkPDU(0);//将回复信息放到resPDU的caData中
            if(ret)
            {
                //在数据库中写入信息成功,服务器回复客户端加入成功
                resPDU->uiMsgType=ENUM_MSG_TYPE_REGIST_RESPONE;
                strcpy(resPDU->caData,REGIST_OK);
            }
            else
            {
                QString str="regist false";
                strcpy(resPDU->caData,REGIST_FAILED);
            }
            //使用socket将存储的信息通过PDU发给客户端
            write((char*)resPDU,pdu->uiPDULen);
            freePDU(resPDU);
            resPDU=nullptr;

            break;
        }

        default:
            break;
    }

    freePDU(pdu);
    pdu=nullptr;

}

服务器返回信息,客户端进行相应接收:

        服务器向客户端发送信号时,产生readyRead信号

        使用socket读取来自客户端的PDU信息,读取方式与服务器的接收过程相同

void TcpClient::recvMsg()
{
    //使用socket读取来自服务器PDU的数据
    qDebug()<<m_tcpSocket.bytesAvailable();
    uint uiPDULen=0;
    m_tcpSocket.read((char*)&uiPDULen,sizeof(uint));//读取总数据大小的信息
    uint uiMsgLen=uiPDULen-sizeof(PDU);//实际信息的长度
    PDU *pdu=mkPDU(uiMsgLen);//创建对应的PDU协议进行读取
    m_tcpSocket.read((char*)pdu+sizeof(uint),uiPDULen-sizeof(uint));
    switch (pdu->uiMsgType) {
        case ENUM_MSG_TYPE_REGIST_RESPONE://回复数据类型
        {
        if(strcmp(pdu->caData,REGIST_OK)==0)
            {
                QMessageBox::information(this,"注册结果","注册成功");
            }
            else
            {
                QMessageBox::warning(this,"注册结果","注册失败");
            }
            break;
        }


        default:
            break;
    }

}

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值