03-客户端服务器搭建(基础)之云盘项目

154 阅读4分钟

03-客户端服务器搭建(基础)

一、 配置文件

1. 资源文件

将客户端和服务器所需要的数据写在配置文件中,例如IP和端口

  • 将服务器IP和PORT信息填入配置文件中;
  • 将配置文件作为资源文件添加到项目中;
  • 程序运行时加载配置文件中的数据;

2. 在QT Creator中新建一个项目,选择基类为QWidget

image-20220622172334628.png

3. 在代码目录下创建一个client.config配置文件

(1)先做本地测试,设置本地回环IP地址127.0.0.1

127.0.0.1 # 回环IP地址
8888 # 端口号
  • 接着在QtCreator中将此文件添加到资源文件中,这样无论项目怎么迁移,资源文件一直都在;(有用过QtCreator的添加图片资源就非常明白了)

image-20220622230418731.png

image-20220622230453622.png

image-20220622230520419.png

  • 添加前缀,区别于其他的资源文件;

image-20220622231954238.png

(2)设置好资源文件后,就是将数据读取出来(用文件进行操作)

小技巧:定位到头文件的声明函数后可以使用alt + 回车,快速跳转到.cpp文件进行函数定义 
// tcpclient.cpp#include "tcpclient.h"
#include "ui_tcpclient.h"
#include <QByteArray>
#include <QDebug>
#include <QMessageBox>
#include <QStringList>
TcpClient::TcpClient(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::TcpClient)
{
    ui->setupUi(this);
    loadConfig();
}
​
TcpClient::~TcpClient()
{
    delete ui;
}
​
void TcpClient::loadConfig()
{
    bool isOpenSF;
    // 将路径赋值到file对象中
    // 资源文件的写法 : + 前缀
    QFile file(":/client.config");
    // 打开文件, 传入参数:打开的方式(读写等等),
    // 若成功打开会返回true
    isOpenSF = file.open(QIODevice::ReadOnly);
    if (isOpenSF)
    {
        // 将资源文件中的数据全部读取出来,作为字节数组存储
        // 再将字节类型转换成字符串,但是这里不能直接进行转换,要变成 char* (const _CharT*)
        QByteArray baData = file.readAll();
        QString strData = baData.toStdString().c_str();
//        qDebug() << strData;
        // 读取完文件后,要关闭
        file.close();
        // 读取完文件后要解析,对字符串进行切割
        // 将/r/n替换成空格
        strData.replace("\r\n", " ");
//        qDebug() << strData;
​
        // 用空格分割, 返回QStringList
        QStringList strList = strData.split(" ");
        int strListSize = strList.size();
//        for (int i = 0; i < strListSize; ++i)
//        {
//            // 将分割的值循环打印出来
//            qDebug() << "<===>" << strList[i];
//        }
        m_strIP = strList.at(0); // IP 地址是字符串
        m_usPort = strList.at(1).toUShort(); // 将字符串端口转换为无符号短整型
//        qDebug() << "IP: " << m_strIP << " port: " << m_usPort;
    }
    else
    {
        // 若打开失败,提示错误
        QMessageBox::critical(this, "open config", "open config failed");
    }
}

2. 客户端实现

(1)TCP客户端连接服务器

  • 先加载配置文件,接着产生socket,然后连接服务器;
  • 连接服务器成功之后,分两步处理:接收服务器数据和发送数据给服务器;

image-20220623182515565.png

(2)在项目文件(.pro)中,加上网络network模块

QT       += core gui network
# 加完后就可以使用QT中的网络编程模块 
  • 在tcpclient.h头文件中添加:
#include <QTcpSocket>
// 连接服务器
// 默认读写,既可以往服务器中写也可以从服务器干读取数据
m_tcpSocket.connectToHost(QHostAddress(m_strIP), m_usPort);

(3)因为连接服务器成功会发出connected()信号,所以在头文件中添加槽函数对信号做处理

void TcpClient::connetServer()
{
    // 信号与槽函数先进行连接关联
    // 参数1 信号的发布者,m_tcpSocket,因为要通过m_tcpSocket来连接服务器
    // 参数2 发布的是什么信号
    // 参数3 信号的处理者,即tcpclient对象
    // 参数4 信号的处理者用什么槽函数进行处理
    connect(&m_tcpSocket, SIGNAL(connected())
            , this, SLOT(showConnect()));
​
    // 连接服务器
    // 默认读写,既可以往服务器中写也可以从服务器干读取数据
    m_tcpSocket.connectToHost(QHostAddress(m_strIP), m_usPort);
}
​
// 要与信号(connected)的处理函数进行关联才行
void TcpClient::showConnect()
{
    // 假设连接服务器成功之后,就会发出connected()信号,接着就可以通过QMessageBox将消息返回
    QMessageBox::information(this, "连接服务器", "连接服务器成功");
}

3. 服务器搭建

(1)新建项目

image-20220624182535901.png

  • 服务器进行与客户端的连接要绑定和监听,需要提供IP和端口号
  • 创建并补充server.config配置文件,且将其添加到项目中,同前面一样

(2)服务器实现过程

  • 加载配置文件
  • 连接数据库
  • 接收客户端的连接
QTcpServer 监听及接收客户端的连接
QTcpSocket 和客户端数据交互

image-20220624204949034.png

(3)继承QTcpServer类,创建一个MyTcpServer派生类

image-20220624205135494.png

  • 为了能让派生的类支持信号和槽,要做两个步骤

    • 要继承public QObject,但是继承的QTcpServer已经继承了这个类,所以就不用写了;

    • 添加Q_OBJECT

image-20220624211551017.png

(4)接收客户端的连接,首先要进行监听,这里采用单例模式

这样做,当后面需要MyTcpServer的地方,可以直接通过类名调用getInstance(),获得静态的局部对象进行操作
// 这样做,当后面需要MyTcpServer的地方,可以直接通过类名调用getInstance(),获得静态的局部对象进行操作
// 静态
MyTcpServer &MyTcpServer::getInstance()
{
    // 定义一个静态的MyTCPServer的对象
    static MyTcpServer instance;
    // 将此对象作为引用返回
    return instance;
}
​

(5)那么如何知道客户端连接了

 void incomingConnection(qintptr handle) override; // 监听后,一旦有客户端连接,就会自动调用此函数(这是虚函数需要重写)

image-20220624231248495.png

// 利用MyTcpServer进行监听之后,只要有客户端连接过来,
// 就会自动调用incomingConnection函数处理
void MyTcpServer::incomingConnection(qintptr handle)
{
    qDebug() << "new client connected";
}
​

(6)完成这些步骤后

先启动服务器端再启动客户端

image-20220624231538928.png

image-20220624231547825.png