C++ 基于Socket和SQLite的智能家居状态建议系统
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' 错误通常是由于访问了无效的内存地址导致的。以下是一些常见的解决思路:
- 检查数组越界: 确保在操作数组时没有越界访问。
- 初始化指针: 确保在使用指针之前将其初始化为有效地址。
- 检查内存分配: 确保在使用动态分配的内存之前分配了足够的内存空间。
- 使用调试工具: 使用调试工具(如gdb)可以帮助定位错误代码的位置。
在提供的代码中,可能导致 'Segmentation fault' 错误的原因包括:
- 数据库查询结果为空: 在
handleClientRequest函数中,如果数据库查询没有匹配的记录,status结构体的device_name字段将为空。在后续代码中使用strlen(status.device_name)判断设备状态信息是否接收成功时,就可能会导致 'Segmentation fault' 错误。 - 客户端读取数据为空: 在
Procession::readyRead()函数中,如果读取的数据为空,后续对空数据的解析操作也可能导致 'Segmentation fault' 错误。
解决这些问题的方法是在进行相关操作之前添加判断条件,例如在使用 strlen 函数之前判断字符串是否为空,在解析数据之前判断数据是否为空等。
原文地址: https://www.cveoy.top/t/topic/fCwY 著作权归作者所有。请勿转载和采集!