C++ 基于Socket和SQLite的智能家居状态建议系统

本文提供了一个使用C++实现的简单智能家居状态建议系统,该系统包含服务器端和客户端代码示例,并结合了Socket网络编程和SQLite数据库操作。

服务器端代码

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

#define MAX_BUFFER_SIZE 1024

typedef struct {
    int uid;
    char device_name[10];
    char device_state[10];
    char value[10];
    char mode[10];
} Status;

typedef struct {
    int sockfd;
    struct sockaddr_in client_addr;
    socklen_t client_addr_len;
    sqlite3 *db;
} ServerContext;

void handleClientRequest(ServerContext *context) {
    char buffer[MAX_BUFFER_SIZE];
    int userid;

    // 接收客户端发送的userid
    ssize_t recvSize = recv(context->sockfd, &userid, sizeof(int), 0);
    if (recvSize == -1) {
        perror('userid接受失败\nrecv');
        return;
    }
    userid = ntohl(userid); // 将网络字节序转换为主机字节序
    printf('客户端已连接\n');
    printf('userid:%d',userid);
    // 查询数据库获取设备状态信息
    char sql[100];
    snprintf(sql, sizeof(sql), 'SELECT * FROM Status WHERE uid = %d', userid);
    sqlite3_stmt *stmt;
    int rc = sqlite3_prepare_v2(context->db, sql, -1, &stmt, NULL);
    if (rc != SQLITE_OK) {
        fprintf(stderr, '无法执行的语句: %s\n', sqlite3_errmsg(context->db));
        return;
    }

    Status status;
    memset(&status, 0, sizeof(Status)); // 清空status结构体
    while (sqlite3_step(stmt) == SQLITE_ROW) {
        status.uid = sqlite3_column_int(stmt, 1);
        printf('%d',status.uid);
        strncpy(status.device_name, sqlite3_column_text(stmt, 2), sizeof(status.device_name));
        printf('%s',status.device_name);
        strncpy(status.device_state, sqlite3_column_text(stmt, 3), sizeof(status.device_state));
        strncpy(status.value, sqlite3_column_text(stmt, 4), sizeof(status.value));
        strncpy(status.mode, sqlite3_column_text(stmt, 5), sizeof(status.mode));
    }

    // 在循环结束后判断是否查询到数据
    if (sqlite3_column_count(stmt) == 0) {
          fprintf(stderr, '查询结果为空\n');
          sqlite3_finalize(stmt);
          return;
      }

    sqlite3_finalize(stmt);

    // ... 后续代码逻辑 ...
}

// ... 其他函数 ...

客户端代码

// ... 其他代码 ...

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

// ... 其他代码 ...

Segmentation fault 错误解决思路

出现 'Segmentation fault' 错误通常是由于访问了无效的内存地址导致的。以下是一些常见的解决思路:

  1. 检查数组越界: 确保在操作数组时没有越界访问。
  2. 初始化指针: 确保在使用指针之前将其初始化为有效地址。
  3. 检查内存分配: 确保在使用动态分配的内存之前分配了足够的内存空间。
  4. 使用调试工具: 使用调试工具(如gdb)可以帮助定位错误代码的位置。

在提供的代码中,可能导致 'Segmentation fault' 错误的原因包括:

  • 数据库查询结果为空:handleClientRequest 函数中,如果数据库查询没有匹配的记录,status 结构体的 device_name 字段将为空。在后续代码中使用 strlen(status.device_name) 判断设备状态信息是否接收成功时,就可能会导致 'Segmentation fault' 错误。
  • 客户端读取数据为空:Procession::readyRead() 函数中,如果读取的数据为空,后续对空数据的解析操作也可能导致 'Segmentation fault' 错误。

解决这些问题的方法是在进行相关操作之前添加判断条件,例如在使用 strlen 函数之前判断字符串是否为空,在解析数据之前判断数据是否为空等。

C++ 基于Socket和SQLite的智能家居状态建议系统

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

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