当前位置: 首页 > news >正文

网编day7(网络词典)(部分)

server.c

#include "my_head.h"#define SER_PORT 8888
#define SER_IP "192.168.195.141"
#define MAX_BUFFER 1024// 定义客户端会话结构
typedef struct
{int clifd;   // 客户端用于与服务器建立连接的文件描述符char username[50];int status;    // 用于标识用户是否已登录的标志
} ClientSession;// 自定义字符检查函数
int is_alphanumeric(char c) {return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9');
}int is_allowed_special(char c) {return c == '@' || c == '.' || c == '_' || c == '-';
}// 输入验证函数
int validate_input(const char *input)
{if (!input || strlen(input) == 0) return 0;if (strlen(input) > 50) return 0;for (int i = 0; input[i] != '\0'; i++){if (!is_alphanumeric(input[i]) && !is_allowed_special(input[i])){return 0;}}return 1;
}// SQL转义函数
void escape_sql_string(char *dest, const char *src, size_t dest_size)
{if (!dest || !src || dest_size == 0) return;size_t j = 0;for (size_t i = 0; src[i] != '\0' && j < dest_size - 1; i++){if (src[i] == '\''){if (j + 2 < dest_size - 1){dest[j++] = '\'';dest[j++] = '\'';}}else{dest[j++] = src[i];}}dest[j] = '\0';
}// 定义一个用于数据库初始化的函数
sqlite3* init_database()
{sqlite3 *ppDb = NULL;if(sqlite3_open("./dict.db",&ppDb) != SQLITE_OK){printf("数据库打开失败!%s\n",sqlite3_errmsg(ppDb));return NULL;}printf("数据库打开成功!\n");// 创建用户信息表char *usr_sql = "create table if not exists users(id integer primary key autoincrement, username text not NULL unique, password text not NULL);";char *errmsg = NULL;if(sqlite3_exec(ppDb,usr_sql,NULL,NULL,&errmsg) != SQLITE_OK){printf("用户信息表创建失败!%s\n",errmsg);sqlite3_free(errmsg);errmsg = NULL;sqlite3_close(ppDb);return NULL;}// 创建历史用户查询记录表char *history_sql = "create table if not exists history(id integer primary key autoincrement, username text not NULL, word text not NULL, time datetime default current_timestamp);";if(sqlite3_exec(ppDb,history_sql,NULL,NULL,&errmsg) != SQLITE_OK){printf("历史用户查询记录表创建失败!%s\n",errmsg);sqlite3_free(errmsg);errmsg = NULL;sqlite3_close(ppDb);return NULL;}return ppDb;     // 成功返回句柄
}// 定义注册函数
void do_register(int clifd, char *user, char *pass, sqlite3 *ppDb)
{// 输入验证if (!validate_input(user) || !validate_input(pass)){const char *msg = "FAIL:输入包含非法字符";send(clifd, msg, strlen(msg), 0);return;}char escaped_user[100], escaped_pass[100];escape_sql_string(escaped_user, user, sizeof(escaped_user));escape_sql_string(escaped_pass, pass, sizeof(escaped_pass));char sql[512];char *errmsg = NULL;sprintf(sql, "insert into users(username, password) values('%s', '%s');", escaped_user, escaped_pass);int rc = sqlite3_exec(ppDb, sql, NULL, NULL, &errmsg);if(rc == SQLITE_OK){const char *msg = "OK";send(clifd, msg, strlen(msg), 0);}else if(rc == SQLITE_CONSTRAINT){const char *msg = "FAIL:用户名已存在";send(clifd, msg, strlen(msg), 0);}else{printf("注册失败: %s\n", errmsg);const char *msg = "FAIL:注册失败";send(clifd, msg, strlen(msg), 0);}if(errmsg){sqlite3_free(errmsg);}
}// 登录回调函数
static int login_callback(void *data, int argc, char **argv, char **azColName)
{int *result = (int *)data;*result = 1;return 0;
}// 定义登录函数
int do_login(int clifd, char *user, char *pass, sqlite3 *ppDb)
{// 输入验证if (!validate_input(user) || !validate_input(pass)){const char *msg = "FAIL:输入包含非法字符";send(clifd, msg, strlen(msg), 0);return 0;}char escaped_user[100], escaped_pass[100];escape_sql_string(escaped_user, user, sizeof(escaped_user));escape_sql_string(escaped_pass, pass, sizeof(escaped_pass));char sql[512];char *errmsg = NULL;int login_success = 0;sprintf(sql, "select id from users where username = '%s' and password = '%s';", escaped_user, escaped_pass);int rc = sqlite3_exec(ppDb, sql, login_callback, &login_success, &errmsg);if(rc != SQLITE_OK){printf("登录查询错误: %s\n", errmsg);const char *msg = "FAIL:服务器错误";send(clifd, msg, strlen(msg), 0);if(errmsg) sqlite3_free(errmsg);return 0;}if(login_success){const char *msg = "OK";send(clifd, msg, strlen(msg), 0);return 1;}else{const char *msg = "FAIL:用户名或密码错误";send(clifd, msg, strlen(msg), 0);return 0;}
}// 定义查询单词函数
void do_query(int clifd, char *user, char *word, sqlite3 *ppDb)
{// 输入验证if (!validate_input(word)){const char *msg = "FAIL:输入包含非法字符";send(clifd, msg, strlen(msg), 0);return;}FILE *fp = fopen("dict.txt", "r");char line[512], temp[100], explanation[400];int found = 0;if(fp == NULL){const char *msg = "FAIL:服务器文件错误";send(clifd, msg, strlen(msg), 0);return;}while(fgets(line, sizeof(line), fp) != NULL){sscanf(line, "%s %[^\n]", temp, explanation);if(strcmp(temp, word) == 0){found = 1;send(clifd, explanation, strlen(explanation), 0);// 插入历史记录char escaped_user[100], escaped_word[100];escape_sql_string(escaped_user, user, sizeof(escaped_user));escape_sql_string(escaped_word, word, sizeof(escaped_word));char sql[512];char *errmsg = NULL;sprintf(sql, "insert into history(username, word) values('%s', '%s');", escaped_user, escaped_word);int rc = sqlite3_exec(ppDb, sql, NULL, NULL, &errmsg);if(rc != SQLITE_OK){printf("插入历史记录错误: %s\n", errmsg);if(errmsg) sqlite3_free(errmsg);}break;}}fclose(fp);if(!found){const char *msg = "NOT FOUND";send(clifd, msg, strlen(msg), 0);}
}// 历史记录回调函数
static int history_callback(void *data, int argc, char **argv, char **azColName)
{char *history_data = (char *)data;char buffer[256];sprintf(buffer, "单词: %s, 时间: %s\n", argv[0], argv[1]);strncat(history_data, buffer, MAX_BUFFER - strlen(history_data) - 1);return 0;
}// 定义查询历史记录函数
void do_history(int clifd, char *user, sqlite3 *ppDb)
{// 输入验证if (!validate_input(user)){const char *msg = "FAIL:输入包含非法字符";send(clifd, msg, strlen(msg), 0);return;}char escaped_user[100];escape_sql_string(escaped_user, user, sizeof(escaped_user));char sql[512];char *errmsg = NULL;char history_data[MAX_BUFFER] = {0};sprintf(sql, "select word, time from history where username = '%s' order by time desc limit 10;", escaped_user);int rc = sqlite3_exec(ppDb, sql, history_callback, history_data, &errmsg);if(rc != SQLITE_OK){printf("查询历史记录错误: %s\n", errmsg);const char *msg = "FAIL:服务器错误";send(clifd, msg, strlen(msg), 0);if(errmsg) sqlite3_free(errmsg);return;}if(strlen(history_data) > 0){send(clifd, history_data, strlen(history_data), 0);}else{const char *msg = "暂无查询历史";send(clifd, msg, strlen(msg), 0);}
}// 处理客户端请求
void handle_client(int clifd, sqlite3 *ppDb)
{ClientSession session;session.clifd = clifd;session.status = 0;session.username[0] = '\0';char buf[MAX_BUFFER];char cmd[20], user[50], pass[50], word[100];int n;while(1){memset(buf, 0, sizeof(buf));n = recv(clifd, buf, sizeof(buf), 0);if(n <= 0){printf("客户端断开连接\n");break;}sscanf(buf, "%s", cmd);if(strcmp(cmd, "REGISTER") == 0){sscanf(buf, "%*s %s %s", user, pass);do_register(clifd, user, pass, ppDb);}else if(strcmp(cmd, "LOGIN") == 0){sscanf(buf, "%*s %s %s", user, pass);if(do_login(clifd, user, pass, ppDb)){session.status = 1;strncpy(session.username, user, sizeof(session.username) - 1);printf("用户 %s 登录成功\n", user);}}else if(strcmp(cmd, "QUERY") == 0){if(!session.status){const char *msg = "FAIL:请先登录";send(clifd, msg, strlen(msg), 0);continue;}sscanf(buf, "%*s %s", word);printf("用户 %s 查询单词: %s\n", session.username, word);do_query(clifd, session.username, word, ppDb);}else if(strcmp(cmd, "HISTORY") == 0){if(!session.status){const char *msg = "FAIL:请先登录";send(clifd, msg, strlen(msg), 0);continue;}printf("用户 %s 查询历史记录\n", session.username);do_history(clifd, session.username, ppDb);}else if(strcmp(cmd, "EXIT") == 0){if(session.status) {printf("用户 %s 退出登录\n", session.username);const char *msg = "退出成功";send(clifd, msg, strlen(msg), 0);} else {const char *msg = "未登录状态";send(clifd, msg, strlen(msg), 0);}session.status = 0;session.username[0] = '\0';}else{const char *msg = "Unknown command";send(clifd, msg, strlen(msg), 0);}}close(clifd);
}int main(int argc, const char *argv[])
{int sockfd, clifd;struct sockaddr_in ser_addr, cli_addr;socklen_t addrlen = sizeof(cli_addr);pid_t pid;sqlite3 *ppDb = NULL;// 初始化数据库ppDb = init_database();if(ppDb == NULL){return -1;}// 创建socketsockfd = socket(AF_INET, SOCK_STREAM, 0);if(sockfd < 0){perror("socket");sqlite3_close(ppDb);return -1;}printf("socket创建成功 fd=%d\n", sockfd);// 设置端口复用int opt = 1;setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));// 绑定地址ser_addr.sin_family = AF_INET;ser_addr.sin_addr.s_addr = htonl(INADDR_ANY);ser_addr.sin_port = htons(SER_PORT);if(bind(sockfd, (struct sockaddr*)&ser_addr, sizeof(ser_addr)) < 0){perror("bind");sqlite3_close(ppDb);close(sockfd);return -1;}printf("bind成功\n");// 监听if(listen(sockfd, 5) < 0){perror("listen");sqlite3_close(ppDb);close(sockfd);return -1;}printf("listen成功,服务器启动在端口 %d\n", SER_PORT);// 忽略子进程退出信号signal(SIGCHLD, SIG_IGN);// 主循环while(1){clifd = accept(sockfd, (struct sockaddr*)&cli_addr, &addrlen);if(clifd < 0){perror("accept");continue;}printf("客户端 [%s] 连接成功, fd=%d\n", inet_ntoa(cli_addr.sin_addr), clifd);pid = fork();if(pid == 0)  // 子进程{close(sockfd);handle_client(clifd, ppDb);exit(0);}else if(pid > 0)  // 父进程{close(clifd);}else{perror("fork");close(clifd);}}sqlite3_close(ppDb);close(sockfd);return 0;
}


文章转载自:

http://VkpzWtvU.xhjjs.cn
http://4auYWdSV.xhjjs.cn
http://MnpqTiqy.xhjjs.cn
http://Ph6O13O1.xhjjs.cn
http://0WDfN0WV.xhjjs.cn
http://jRPxc9DS.xhjjs.cn
http://JwAaM9vY.xhjjs.cn
http://w8sNCMm0.xhjjs.cn
http://lJD0ZGkj.xhjjs.cn
http://jgNzpHb7.xhjjs.cn
http://DIUH8Ybp.xhjjs.cn
http://tuz6Krqe.xhjjs.cn
http://5zxXx4YL.xhjjs.cn
http://z5sHh9nV.xhjjs.cn
http://biPt77Xy.xhjjs.cn
http://rQaDZjl6.xhjjs.cn
http://2ME0Aob1.xhjjs.cn
http://v8Kbvlz2.xhjjs.cn
http://J9uDENbD.xhjjs.cn
http://WlMgWCGQ.xhjjs.cn
http://j6uIQCOh.xhjjs.cn
http://eVJbMydH.xhjjs.cn
http://vX617q5T.xhjjs.cn
http://InMvwX5v.xhjjs.cn
http://LsatXNSy.xhjjs.cn
http://UltqhKGY.xhjjs.cn
http://dMDsdaq5.xhjjs.cn
http://5TbungPB.xhjjs.cn
http://2DDmL9d4.xhjjs.cn
http://OKZGrMW6.xhjjs.cn
http://www.dtcms.com/a/386832.html

相关文章:

  • CodeBuddy AI 深度体验:模型怎么选不踩坑?
  • MQ高级.
  • 46.Mysql基础及案例
  • 贪心算法应用:文件合并问题详解
  • 什么是“孤块”?
  • 神卓N600 公网盒子公网访问群晖NAS绿联飞牛
  • 浅谈背包DP(C++实现,配合lc经典习题讲解)
  • 虚拟化嵌套支持在云服务器容器化Hyper-V环境的配置标准
  • 修改el-checkbox默认颜色
  • ROS接口信息整理
  • 【C++11】lambda匿名函数、包装器、新的类功能
  • 【Linux系统】深入理解线程,互斥及其原理
  • 1. C++ 中的 C
  • 探讨基于国产化架构的非结构化数据管理平台建设路径与实践
  • C++11移动语义
  • 代码随想录第14天| 翻转、对称与深度
  • 算法改进篇 | 改进 YOLOv12 的水面垃圾检测方法
  • 一个我自己研发的支持k-th路径查询的数据结构-owl tree
  • 首款“MODA”游戏《秘境战盟》将在Steam 新品节中开放公开试玩
  • ε-δ语言(Epsilon–Delta 语言)
  • QCA9882 Module with IPQ4019 Mainboard High-Performance Mesh Solution
  • xv6实验:Ubuntu2004 WSL2实验环境配置(包括git clone网络问题解决方法)
  • ICE-Interactive Connectivity Establishment-交互式连接建立
  • 【代码随想录day 28】 力扣 45.跳跃游戏 II
  • IP核的底层封装
  • 4.PFC原理和双闭环控制
  • 江苏保安员证【单选题】考试题库及答案
  • 71-Python+MySQL 医院挂号问诊管理系统-1
  • 图片重命名
  • 同网段通信ARP