智能家居系统:QT C++ 客户端与 Linux C 服务器的 HTTP 通信

数据库设计

  • 创建用户表
CREATE TABLE IF NOT EXISTS users (
    uid INTEGER PRIMARY KEY AUTOINCREMENT,
    username varchar(10), 
    passwd varchar(10)
);


-- 创建智能家居状态表
CREATE TABLE IF NOT EXISTS Status (
    sid INTEGER PRIMARY KEY AUTOINCREMENT,
    uid INTEGER ,
    device_name varchar(10),
    device_state varchar(10),
    value varchar(10),
    mode varchar(10),
    FOREIGN KEY (uid) REFERENCES users (uid)
);

系统架构

  • 客户端是 QT C++ 写的,服务器端是 Linux C 写的
  • 客户端与服务器之间进行 HTTP 通信

服务器端设计

服务器主要设计模块如下

  • void startServer(): 启动服务器,监听特定端口
  • void acceptConnection(): 接受客户端连接
  • void processClientData(string data): 处理客户端发来的数据
  • void sendDataToClient(string data): 将数据发送给客户端
  • void closeConnection(): 关闭与客户端的连接
  • void viewData(): 查看客户端存储在 SQlite 智能家居状态表中温度和湿度数据
  • void analyzeData(): 根据温度和湿度数据分析出合理建议

客户端与服务器交互流程

  1. 客户端将 URL 打包成 JSON 并通过 HTTP 通信发送给服务器
  2. 服务器解析 JSON,验证是否可以和客户端进行通信
  3. 连接 SQLite 数据库
  4. 根据 Status 表的空调温度、加湿器湿度向客户端发送建议(例如温度低于 24 摄氏度、湿度小于 40% 大于 70% 时,服务器将发送 '空调温度过低,建议提高温度至 26℃;加湿器湿度过高或过低,建议调整加湿器湿度' 给客户端,客户端显示在 GUI)

代码示例

客户端 QT C++

客户在主界面点击进入该界面 QWidget,当客户在该界面按下 QPushButton 后和服务器进行 HTTP 通信,连接成功后在 UI 的 LIneEdit 上显示 '服务器已连接',连接失败在 UI 的 LIneEdit 上显示 '服务器已连接',并将网址 URL 打包成 JSON 文件给服务器,并将服务器发送的信息在 UI 打印出来,头文件和 .cpp 分开内容:以下是一个简单的示例代码,展示了如何在 QT C++ 中实现客户端与服务器之间的 HTTP 通信。

客户端头文件 (client.h)

#ifndef CLIENT_H
#define CLIENT_H

#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>

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

signals:
    void connected();
    void connectionFailed();
    void dataReceived(QString data);

public slots:
    void connectToServer(QString serverAddress, int port);
    void sendData(QString data);

private slots:
    void handleNetworkReply(QNetworkReply *reply);

private:
    QNetworkAccessManager *networkManager;
};

#endif // CLIENT_H

客户端源文件 (client.cpp)

#include "client.h"

Client::Client(QObject *parent) : QObject(parent)
{
    networkManager = new QNetworkAccessManager(this);
    connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkReply(QNetworkReply*)));
}

void Client::connectToServer(QString serverAddress, int port)
{
    // 创建服务器地址
    QUrl url;
    url.setScheme("http");
    url.setHost(serverAddress);
    url.setPort(port);

    // 发送连接请求
    QNetworkRequest request(url);
    QNetworkReply *reply = networkManager->get(request);
    connect(reply, SIGNAL(finished()), this, SLOT(connected()));
    connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(connectionFailed()));
}

void Client::sendData(QString data)
{
    // 创建服务器地址
    QUrl url;
    url.setScheme("http");
    url.setHost(serverAddress);
    url.setPort(port);

    // 发送数据
    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    QNetworkReply *reply = networkManager->post(request, data.toUtf8());
    connect(reply, SIGNAL(finished()), this, SLOT(handleNetworkReply(QNetworkReply*)));
}

void Client::handleNetworkReply(QNetworkReply *reply)
{
    if (reply->error() == QNetworkReply::NoError) {
        // 读取服务器响应的数据
        QString data = reply->readAll();
        emit dataReceived(data);
    } else {
        // 处理错误
    }

    reply->deleteLater();
}

服务器端代码 (Linux C)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>

#define PORT 8080
#define MAX_BUFFER_SIZE 1024

void processClientData(int clientSocket, char *data) {
    // 处理客户端发来的数据
    // 解析 JSON 数据并进行相应操作
    // ...

    // 发送响应数据给客户端
    char response[] = "Server response";
    send(clientSocket, response, strlen(response), 0);
}

int main(int argc, char *argv[]) {
    int serverSocket, clientSocket;
    struct sockaddr_in serverAddress, clientAddress;
    char buffer[MAX_BUFFER_SIZE];

    // 创建服务器套接字
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket == -1) {
        perror("Failed to create socket");
        exit(EXIT_FAILURE);
    }

    // 设置服务器地址和端口
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = INADDR_ANY;
    serverAddress.sin_port = htons(PORT);

    // 绑定服务器地址和端口
    if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
        perror("Failed to bind");
        exit(EXIT_FAILURE);
    }

    // 监听端口
    if (listen(serverSocket, 3) < 0) {
        perror("Failed to listen");
        exit(EXIT_FAILURE);
    }

    printf("Server is running on port %d\n", PORT);

    while (1) {
        // 接受客户端连接
        int clientAddressLength = sizeof(clientAddress);
        clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, (socklen_t *)&clientAddressLength);
        if (clientSocket < 0) {
            perror("Failed to accept");
            exit(EXIT_FAILURE);
        }

        // 接收客户端发来的数据
        memset(buffer, 0, sizeof(buffer));
        if (recv(clientSocket, buffer, sizeof(buffer), 0) < 0) {
            perror("Failed to receive data");
            exit(EXIT_FAILURE);
        }

        printf("Received data from client: %s\n", buffer);

        // 处理客户端数据
        processClientData(clientSocket, buffer);

        // 关闭与客户端的连接
        close(clientSocket);
    }

    // 关闭服务器套接字
    close(serverSocket);

    return 0;
}

请注意,此代码仅为示例,可能需要根据实际需求进行修改和完善。

智能家居系统:QT C++ 客户端与 Linux C 服务器的 HTTP 通信

原文地址: https://www.cveoy.top/t/topic/fBvK 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录