Qt C++客户端与Linux C服务器HTTP通信及智能家居建议实战

这篇博客将提供一个简单的示例,演示如何使用Qt C++编写客户端和Linux C编写服务器,实现两者之间的HTTP数据通信。此外,还将展示如何从智能家居状态表中获取最新的温度和湿度数据,并根据这些数据向客户端发送建议。

1. 数据库设计

首先,我们需要创建两个表:用户表和智能家居状态表。

用户表 (users):

CREATE TABLE IF NOT EXISTS users (
    uid INTEGER PRIMARY KEY AUTOINCREMENT,
    username varchar(10),
    passwd varchar(10)
);

智能家居状态表 (Status):

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)
);

2. 客户端代码 (Qt C++)

#include <QtWidgets>
#include <QtNetwork>

class Client : public QWidget
{
    Q_OBJECT

public:
    Client(QWidget *parent = nullptr);

private slots:
    void connectToServer();
    void sendMessage();
    void receiveMessage();
    void getAdvice();

private:
    QLineEdit *urlLineEdit;
    QLineEdit *sendMessageLineEdit;
    QLineEdit *receiveMessageLineEdit;
    QLineEdit *adviceLineEdit;
    QPushButton *connectButton;
    QPushButton *sendMessageButton;
    QPushButton *getAdviceButton;
    QNetworkAccessManager *networkManager;
    QNetworkReply *reply;

    void parseAdvice(const QString &advice);
};

Client::Client(QWidget *parent)
    : QWidget(parent)
{
    urlLineEdit = new QLineEdit('http://localhost:8080', this);
    sendMessageLineEdit = new QLineEdit(this);
    receiveMessageLineEdit = new QLineEdit(this);
    adviceLineEdit = new QLineEdit(this);
    connectButton = new QPushButton('Connect', this);
    sendMessageButton = new QPushButton('Send Message', this);
    getAdviceButton = new QPushButton('Get Advice', this);
    networkManager = new QNetworkAccessManager(this);

    QVBoxLayout *layout = new QVBoxLayout;
    layout->addWidget(new QLabel('URL:', this));
    layout->addWidget(urlLineEdit);
    layout->addWidget(new QLabel('Send Message:', this));
    layout->addWidget(sendMessageLineEdit);
    layout->addWidget(new QLabel('Receive Message:', this));
    layout->addWidget(receiveMessageLineEdit);
    layout->addWidget(new QLabel('Advice:', this));
    layout->addWidget(adviceLineEdit);
    layout->addWidget(connectButton);
    layout->addWidget(sendMessageButton);
    layout->addWidget(getAdviceButton);

    setLayout(layout);

    connect(connectButton, &QPushButton::clicked, this, &Client::connectToServer);
    connect(sendMessageButton, &QPushButton::clicked, this, &Client::sendMessage);
    connect(getAdviceButton, &QPushButton::clicked, this, &Client::getAdvice);
    connect(networkManager, &QNetworkAccessManager::finished, this, &Client::receiveMessage);
}

void Client::connectToServer()
{
    QUrl url(urlLineEdit->text());
    if (!url.isValid()) {
        qDebug() << 'Invalid URL';
        return;
    }

    QNetworkRequest request(url);
    reply = networkManager->get(request);
}

void Client::sendMessage()
{
    QUrl url(urlLineEdit->text());
    if (!url.isValid()) {
        qDebug() << 'Invalid URL';
        return;
    }

    QNetworkRequest request(url);
    request.setHeader(QNetworkRequest::ContentTypeHeader, 'text/plain');

    QByteArray message = sendMessageLineEdit->text().toUtf8();
    reply = networkManager->post(request, message);
}

void Client::receiveMessage()
{
    if (reply->error() == QNetworkReply::NoError) {
        QString response = QString::fromUtf8(reply->readAll());
        receiveMessageLineEdit->setText(response);
    } else {
        qDebug() << 'Error:' << reply->errorString();
    }

    reply->deleteLater();
}

void Client::getAdvice()
{
    // Assuming the advice is obtained from the server in the response
    QString response = receiveMessageLineEdit->text();
    parseAdvice(response);
}

void Client::parseAdvice(const QString &advice)
{
    // Parse the advice and display it in the GUI
    adviceLineEdit->setText(advice);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    Client client;
    client.show();

    return app.exec();
}

#include 'main.moc'

3. 服务器端代码 (Linux C)

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

#define SERVER_PORT 8080
#define MAX_BUFFER_SIZE 1024

void handleClient(int clientSocket);

int main()
{
    int serverSocket, clientSocket;
    struct sockaddr_in serverAddress, clientAddress;
    socklen_t clientAddressLength = sizeof(clientAddress);

    // Create server socket
    serverSocket = socket(AF_INET, SOCK_STREAM, 0);
    if (serverSocket < 0) {
        perror('Failed to create server socket');
        exit(EXIT_FAILURE);
    }

    // Set server address
    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);
    serverAddress.sin_port = htons(SERVER_PORT);

    // Bind server socket to server address
    if (bind(serverSocket, (struct sockaddr *)&serverAddress, sizeof(serverAddress)) < 0) {
        perror('Failed to bind server socket');
        exit(EXIT_FAILURE);
    }

    // Listen for incoming connections
    if (listen(serverSocket, 1) < 0) {
        perror('Failed to listen for connections');
        exit(EXIT_FAILURE);
    }

    printf('Server listening on port %d\n', SERVER_PORT);

    while (1) {
        // Accept client connection
        clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddress, &clientAddressLength);
        if (clientSocket < 0) {
            perror('Failed to accept client connection');
            exit(EXIT_FAILURE);
        }

        printf('Client connected from %s:%d\n', inet_ntoa(clientAddress.sin_addr), ntohs(clientAddress.sin_port));

        // Handle client request
        handleClient(clientSocket);

        // Close client socket
        close(clientSocket);

        printf('Client disconnected\n');
    }

    // Close server socket
    close(serverSocket);

    return 0;
}

void handleClient(int clientSocket)
{
    char buffer[MAX_BUFFER_SIZE];
    ssize_t bytesRead;
    ssize_t bytesSent;

    // Receive message from client
    bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
    if (bytesRead < 0) {
        perror('Failed to receive message from client');
        exit(EXIT_FAILURE);
    }

    printf('Received message from client: %.*s\n', (int)bytesRead, buffer);

    // **获取智能家居状态表最新的温度、湿度数据**
    // (此处需要根据实际情况编写代码,例如连接数据库并查询数据)
    // 例如:
    float temperature = 22.5; // 从数据库获取的温度数据
    int humidity = 35; // 从数据库获取的湿度数据

    // **制定建议**
    char advice[MAX_BUFFER_SIZE];
    if (temperature < 24.0 && (humidity < 40 || humidity > 70)) {
        snprintf(advice, sizeof(advice), '空调温度过低,建议提高温度至26℃;加湿器湿度过高或过低,建议调整加湿器湿度');
    } else {
        snprintf(advice, sizeof(advice), '当前环境舒适');
    }

    // Send advice to client
    bytesSent = send(clientSocket, advice, strlen(advice), 0);
    if (bytesSent < 0) {
        perror('Failed to send advice to client');
        exit(EXIT_FAILURE);
    }

    printf('Sent advice to client: %.*s\n', (int)bytesSent, advice);
}

4. GUI界面说明

GUI界面包含以下元素:

  • 4个LineEdit:
    • 网址:用于输入服务器地址和端口号。
    • 客户端发送消息:用于输入要发送给服务器的消息。
    • 客户端收到服务器端发送的消息:用于显示服务器返回的消息。
    • 客户端收到服务器发送的建议:用于显示服务器根据智能家居状态发送的建议。
  • 3个QPushButton按钮:
    • 连接客户端和服务器端:用于建立客户端与服务器之间的连接。
    • 客户端发送消息按键:用于向服务器发送消息。
    • 客户端获取服务器端建议的按键:用于向服务器请求智能家居建议。

5. 总结

本文提供了一个简单的客户端Qt C++和Linux C服务器进行http数据通信的示例代码,并展示了如何从智能家居状态表中获取最新的温度和湿度数据,并根据这些数据向客户端发送建议。你可以根据自己的需求对代码进行修改和扩展,例如添加用户认证、数据加密等功能,构建更加完善的智能家居系统。

希望这篇文章能够帮助你理解如何使用Qt C++和Linux C进行网络编程,以及如何构建简单的智能家居系统。

Qt C++客户端与Linux C服务器HTTP通信及智能家居建议

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

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