一、class:struct 的升级版

cpp

// C 的 struct:只能装变量
struct Client {
    int fd;
};

// C++ 的 class:变量+函数可以装一起
class Client : public QObject {
    int fd;
    void sendCommand(const QString &cmd);  // 函数可以放里面
};

二、:: 作用域解析 —— "属于哪个类"

写法 含义
Client::Client() Client类的构造函数(类的构造函数 必须 与类同名)
Client::onConnected() Client类的onConnected函数
QTcpSocket::connected QTcpSocket类的connected信号(系统函数)
QTcpSocket::readyRead QTcpSocket类的readyRead信号

规则: 左边::右边 = "左边类里的右边函数"


三、构造函数初始化

cpp

Client::Client(QObject *parent)  // 参数名可以随便起
    : QObject(parent)             // 初始化列表:先初始化父类
{
    // 构造函数体:真正的初始化操作
    m_socket = new QTcpSocket(this);
    m_serverPort = 0;
}

四、信号与槽 —— Qt 的"回调"

声明(头文件)

cpp

signals:
    void connected();          // 信号:只有声明
    void tagReceived(QString, QString);

private slots:
    void onConnected();        // 槽:普通函数,能被信号触发
    void onReadyRead();

连接(构造函数里)

connect(m_socket, &QTcpSocket::connected,
        this, &Client::onConnected);
//       ↑          ↑               ↑
//    谁发信号    发什么信号      哪个槽函数处理

&类名::函数名 = 取成员函数地址,告诉 connect 连的是哪个函数。

发射(触发时)

cpp

emit tagReceived(epc, tid);
// 所有 connect 了这个信号的槽都会被自动调用

五、QTcpSocket —— TCP 通信

四个自带信号

信号 触发时机
connected() TCP 三次握手成功
disconnected() TCP 断开
readyRead() 收到数据(最重要的)
errorOccurred() 连接失败/超时

异步连接

cpp

m_socket->connectToHost(QHostAddress("192.168.0.165"), 8888);
// 立即返回,不阻塞
// 连上了 → connected() 信号
// 连不上 → errorOccurred() 信号

六、用 cJSON(不是 Qt 的 JSON)

为什么要转来转去?

QString               ← Qt界面统一用这个
    ↓ .toUtf8().constData()

const char*           ← cJSON只认C字符串
    ↓ cJSON_AddStringToObject

cJSON对象              ← 内存中的JSON结构
    ↓ cJSON_PrintUnformatted

char*                 ← C字符串
    ↓ QByteArray(data)

QByteArray            ← Qt字节数组
    ↓ .append('\n')
                      ← 加\n做消息分隔
    ↓ m_socket->write()
TCP发出去              ← 网络传输
Qt 类 存什么 用在哪儿
QString 文本(Unicode) 界面显示
QByteArray 原始字节 网络传输、文件读写
QTcpSocket TCP连接 收发数据

七、写好的 Client 类接口

cpp

class Client : public QObject {
public:
    explicit Client(QObject *parent = nullptr);
    ~Client();

    void connectToServer(const QString &ip, quint16 port);
    void disconnectFromServer();
    void sendCommand(const QString &cmd);
    bool isConnected() const;

signals:
    void connected();
    void disconnected();
    void connectionError(const QString &errorMsg);
    void tagReceived(const QString &epc, const QString &tid);
    void scanDone(int count);

private slots:
    void onConnected();
    void onDisconnected();
    void onReadyRead();
    void onError(QAbstractSocket::SocketError error);

private:
    void parseBuffer();
    QTcpSocket *m_socket;
    QByteArray m_recvBuffer;
    QString m_serverIp;
    quint16 m_serverPort;
};
概念 说明
explicit 防呆锁,禁止隐式转换
QObject *parent = nullptr 默认参数,不传时自动为nullptr
: QObject(parent) 初始化列表,在{}之前调用父类构造
new QTcpSocket(this) 创建对象 + 指定父对象(Qt自动管理内存)
m_ 前缀 成员变量命名习惯(member)

更多推荐