C 语言服务器与 Qt 客户端通信实现智能家居建议系统

本项目使用 C 语言编写服务器,与 Qt 客户端进行 TCP 通信,并使用 SQLite 数据库存储智能家居设备状态,根据设备状态分析并生成建议,并将建议发送给客户端。

客户端代码(Qt)

#include "procession.h"
#include "ui_procession.h"
#include <QAbstractSocket>
#include <QDebug>

Procession::Procession(int userid,QWidget *parent) : 
    QWidget(parent), 
    ui(new Ui::Procession), 
    userid(userid) 
{
    ui->setupUi(this);
    processionWidget();
    m_socket = new QTcpSocket(this);
    connect(ui->connectBtn, &QPushButton::clicked, this, &Procession::on_pushButton_clicked);
    connect(m_socket, &QTcpSocket::readyRead, this, &Procession::readyRead);
    connect(m_socket, &QTcpSocket::connected, this, &Procession::connected);
    connect(m_socket, &QTcpSocket::disconnected,this,&Procession::disconnected);
    connect(m_socket, QOverload<QAbstractSocket::SocketError>::of(&QTcpSocket::error), this, &Procession::displayError);
}

Procession::~Procession() 
{
    delete ui;
}

void Procession::processionWidget() 
{
    setWindowTitle('服务器通信');
    setAutoFillBackground(true);
    QPalette palette=this->palette();
    QPixmap pixmap(":/user/image/image/net.jpg");
    palette.setBrush(QPalette::Window, QBrush(pixmap));
    setPalette(palette);
    setFixedSize(600,400);
}
void Procession::on_pushButton_clicked() 
{
    if (m_socket->state() == QAbstractSocket::ConnectedState) { 
        ui->message->append("已经连接上服务器");
        return;
    }

    QString ip = ui->IP->text();
    QString port = ui->port->text();

    if (ip.isEmpty() || port.isEmpty()) { 
        ui->message->clear();
        ui->message->append("请输入有效的IP地址和端口号");
        return;
    }

    ui->message->clear();
    ui->message->append("正在连接中...");
    m_socket->connectToHost(ip, static_cast<quint16>(ui->port->text().toInt()));
}

void Procession::connected() 
{
    ui->message->append("连接成功");
    // 发送userid给服务器
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out << this->userid;
    if (m_socket->write(block) == -1) { 
        ui->message->append("发送userid失败");
        m_socket->close();
    }
}

void Procession::disconnected() 
{
    ui->message->append("连接失败");
    m_socket->close();
}

void Procession::readyRead() 
{
    QByteArray data = m_socket->readAll();
    if (data.isEmpty()) { 
        ui->message->append("读取的数据为空");
        return;
    }
    // 解析服务器返回的数据
    QDataStream in(&data, QIODevice::ReadOnly);
    QString suggestion;
    in >> suggestion; // 使用重载的 >> 运算符来读取数据
    if (in.status() != QDataStream::Ok) { 
        ui->message->append("解析服务器返回的数据失败");
        return;
    }
    ui->message->append(suggestion);
    m_socket->close();
}

void Procession::displayError(QAbstractSocket::SocketError error) 
{
    QString errorMessage;
    switch (error) { 
    case QAbstractSocket::ConnectionRefusedError:
        errorMessage = "连接被拒绝";
        break;
    case QAbstractSocket::RemoteHostClosedError:
        errorMessage = "远程主机关闭";
        break;
    case QAbstractSocket::HostNotFoundError:
        errorMessage = "未找到主机";
        break;
    case QAbstractSocket::SocketTimeoutError:
        errorMessage = "连接超时";
        break;
    case QAbstractSocket::NetworkError:
        errorMessage = "网络错误";
        break;
    default:
        errorMessage = "未知错误";
        break;
    }
    ui->message->append("连接失败:" + errorMessage);
}

服务器代码(C 语言)

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

#define MAX_BUFFER_SIZE 1024

// 数据库回调函数,用于处理查询结果
static int callback(void *data, int argc, char **argv, char **azColName) {
    char *suggestion = (char *)data;
    if (argc > 0) {
        sprintf(suggestion, "%s%s:%s", suggestion, argv[1], argv[2]);
    }
    return 0;
}

int main() {
    int serverSocket, clientSocket;
    struct sockaddr_in serverAddr, clientAddr;
    socklen_t addrLen = sizeof(struct sockaddr_in);
    char buffer[MAX_BUFFER_SIZE];
    char suggestion[MAX_BUFFER_SIZE];
    sqlite3 *db;
    char *errMsg;

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

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

    // 绑定服务器套接字到指定地址和端口
    if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1) {
        perror("Failed to bind socket");
        exit(EXIT_FAILURE);
    }

    // 监听连接请求
    if (listen(serverSocket, 5) == -1) {
        perror("Failed to listen on socket");
        exit(EXIT_FAILURE);
    }

    printf("Server is listening on port 12345...
");

    while (1) {
        // 接受客户端连接
        clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &addrLen);
        if (clientSocket == -1) {
            perror("Failed to accept client connection");
            continue;
        }

        printf("Accepted a client connection
");

        // 接收客户端发送的userid
        ssize_t bytesRead = recv(clientSocket, buffer, sizeof(buffer), 0);
        if (bytesRead <= 0) {
            perror("Failed to receive userid");
            close(clientSocket);
            continue;
        }

        int userid = atoi(buffer);
        printf("Received userid: %d
", userid);

        // 连接数据库
        if (sqlite3_open("database.db", &db) != SQLITE_OK) {
            perror("Failed to open database");
            close(clientSocket);
            continue;
        }

        // 查询最新的设备状态和建议
        sprintf(buffer, "SELECT device_name, value FROM Status WHERE uid = %d ORDER BY sid DESC LIMIT 1;", userid);
        if (sqlite3_exec(db, buffer, callback, suggestion, &errMsg) != SQLITE_OK) {
            perror("Failed to execute query");
            sqlite3_free(errMsg);
            sqlite3_close(db);
            close(clientSocket);
            continue;
        }

        // 发送建议给客户端
        ssize_t bytesSent = send(clientSocket, suggestion, strlen(suggestion), 0);
        if (bytesSent <= 0) {
            perror("Failed to send suggestion");
        }

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

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

    return 0;
}

数据库(SQLite)

database.db
-- 创建用户表
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)
);

说明

  1. 客户端代码:使用 Qt 编写 GUI 界面,包含连接按钮、IP 地址输入框、端口号输入框和信息显示区域。
  2. 服务器代码:使用 C 语言编写,监听指定端口,接收来自客户端的连接请求,处理用户 ID 和数据库查询,将分析结果发送给客户端。
  3. 数据库代码:使用 SQLite 数据库存储智能家居设备状态信息,包含用户 ID、设备名称、状态、值和模式等字段。

运行流程

  1. 启动服务器,监听指定端口。
  2. 启动客户端,输入服务器 IP 地址和端口号。
  3. 点击连接按钮,客户端与服务器建立连接。
  4. 客户端发送用户 ID 给服务器。
  5. 服务器根据用户 ID 从数据库查询设备状态信息。
  6. 服务器分析设备状态信息,生成建议信息。
  7. 服务器将建议信息发送给客户端。
  8. 客户端接收建议信息并显示在界面上。

注意事项

  1. 服务器和客户端需要在同一网络下。
  2. 数据库文件需要位于服务器端。
  3. 需要根据实际需求修改代码和数据库表结构。

未来展望

  1. 扩展支持更多设备类型和功能。
  2. 实现更智能的建议生成算法。
  3. 开发移动客户端,实现远程控制。
  4. 使用云服务,实现数据存储和分析。

本项目提供了一个简单的示例,可作为智能家居建议系统的基础框架。您可以根据自己的需求进行扩展和完善。

C 语言服务器与 Qt 客户端通信实现智能家居建议系统

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

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