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

国外域名抢注网站wordpress文章详情模版替换

国外域名抢注网站,wordpress文章详情模版替换,医院门户网站模板,wordpress建企业网站设置#x1f4cb; 项目介绍 本项目是一个基于Linux环境的简易云盘系统#xff0c;采用C/S#xff08;客户端/服务器#xff09;架构#xff0c;实现了类似百度网盘的基本功能。系统通过TCP Socket进行网络通信#xff0c;使用JSON格式进行数据交换#xff0c;利用SQLite3数据… 项目介绍 本项目是一个基于Linux环境的简易云盘系统采用C/S客户端/服务器架构实现了类似百度网盘的基本功能。系统通过TCP Socket进行网络通信使用JSON格式进行数据交换利用SQLite3数据库存储用户信息和文件元数据并通过MD5算法实现文件完整性校验和秒传功能。 该系统支持多用户并发访问具有完善的权限管理机制区分普通用户、会员用户和管理员三种角色为不同用户提供差异化的服务。实现的功能 1. 用户管理功能 用户注册与登录新用户可以注册账号已注册用户可以登录系统用户角色管理支持普通用户、会员用户、管理员三种角色账户注销用户可以主动删除自己的账户及所有相关数据 2. 文件管理功能 文件上传支持任意类型文件的上传自动进行MD5校验文件下载可以下载服务器上的文件到本地文件搜索支持按文件名关键字搜索服务器文件秒传功能相同文件MD5值相同无需重复上传实现秒传 3. 历史记录管理 查看上传历史用户可以查看自己的文件上传记录查看下载历史用户可以查看自己的文件下载记录删除历史记录支持删除单条或全部历史记录下载记录删除时可选择同时删除本地文件 4. 权限控制 文件大小限制普通用户上传/下载文件大小限制为20KB会员无限制管理员特权 设置/取消用户会员资格删除其他用户账户管理员账户除外5. 系统特性 多客户端并发支持最多30个客户端同时在线实时状态显示服务器端实时显示在线用户列表数据完整性保证使用MD5校验确保文件传输的完整性 ✨ 项目亮点 1. 秒传技术实现 通过MD5算法计算文件指纹相同内容的文件只需存储一份大大节省服务器存储空间同时实现瞬间上传的用户体验。 2. 完善的权限管理系统 三级用户权限体系普通用户、会员、管理员不同权限享有不同的功能和限制体现了实际云盘系统的设计理念。 3. 健壮的网络通信机制 使用长度前缀的方式传输JSON数据避免粘包问题实现了完整的错误处理和断线重连机制采用多线程处理客户端请求提高并发性能 4. 用户友好的交互设计 清晰的菜单系统根据用户身份动态显示可用功能详细的操作提示和错误信息反馈支持本地文件管理下载文件的删除选择 5. 模块化的代码结构 代码结构清晰功能模块化易于维护和扩展。 ️ 核心技术 1. TCP Socket编程 使用标准的BSD Socket API实现网络通信服务器端使用bind()、listen()、accept()建立监听客户端使用connect()连接服务器通过read()/write()进行数据传输 2. 多线程并发处理 使用POSIX线程库pthread实现多客户端并发处理每个客户端连接创建独立线程处理请求使用互斥锁mutex保护共享资源数据库、客户端列表 3. JSON数据交换 使用json-c库进行JSON数据的解析和生成所有客户端-服务器通信采用JSON格式便于数据结构的扩展和跨平台兼容 4. SQLite3数据库 轻量级嵌入式数据库无需独立的数据库服务器存储用户信息、文件元数据、上传下载历史支持事务处理保证数据一致性 5. MD5文件校验 使用OpenSSL库的MD5功能计算文件的MD5值用于完整性校验和去重实现秒传功能的核心技术依赖库说明 1. pthreadPOSIX线程库 作用提供多线程支持实现并发处理安装命令# Ubuntu/Debian sudo apt-get install libpthread-stubs0-dev# CentOS/RHEL sudo yum install glibc-devel2. json-cJSON处理库 作用解析和生成JSON格式数据安装命令# Ubuntu/Debian sudo apt-get install libjson-c-dev# CentOS/RHEL sudo yum install json-c-devel3. OpenSSL加密库 作用提供MD5哈希算法支持安装命令# Ubuntu/Debian sudo apt-get install libssl-dev# CentOS/RHEL sudo yum install openssl-devel4. SQLite3数据库库 作用提供轻量级数据库功能安装命令# Ubuntu/Debian sudo apt-get install libsqlite3-dev sqlite3# CentOS/RHEL sudo yum install sqlite-devel sqlite完整代码 client.c #include stdlib.h #include string.h #include unistd.h #include arpa/inet.h #include sys/socket.h #include json-c/json.h #include openssl/md5.h #include sys/stat.h #include libgen.h#define BUFFER_SIZE 4096 #define SERVER_IP 127.0.0.1 #define PORT 8888 #define STORAGE_DIR client_storage// 全局客户端状态 int sock; int is_logged_in 0, is_admin 0, is_member 0, user_id -1; char username[50];void send_request(json_object *req); json_object* receive_response(); char* calculate_file_md5(const char *filepath); int receive_file(const char *filepath, long long filesize); int send_file(const char *filepath); void pre_login_menu(); void post_login_menu(); void handle_register(); void handle_login(); void handle_logout(); void handle_upload(); void handle_download(); void handle_search(); void handle_view_history(const char* type); void handle_delete_history(); void handle_delete_account(); void handle_admin_set_member(); void handle_admin_delete_user();void safe_exit(int status) {if(sock) close(sock);exit(status); }int main() {struct sockaddr_in server_addr;mkdir(STORAGE_DIR, 0777);sock socket(AF_INET, SOCK_STREAM, 0);if (sock -1) {perror(无法创建套接字);return 1;}server_addr.sin_family AF_INET;server_addr.sin_addr.s_addr inet_addr(SERVER_IP);server_addr.sin_port htons(PORT);if (connect(sock, (struct sockaddr *)server_addr, sizeof(server_addr)) 0) {perror(连接服务器失败);close(sock);return 1;}printf(已连接到服务器。\n);while (1) {if (!is_logged_in) {pre_login_menu();} else {post_login_menu();}}close(sock);return 0; }void send_request(json_object *req) {const char *req_str json_object_to_json_string(req);uint32_t len htonl(strlen(req_str));if(write(sock, len, sizeof(len)) 0 || write(sock, req_str, strlen(req_str)) 0){printf(发送请求失败与服务器断开连接。\n);safe_exit(1);} }int read_all(void *buf, size_t len) {size_t bytes_read 0;while (bytes_read len) {ssize_t res read(sock, (char*)buf bytes_read, len - bytes_read);if (res 0) return -1;bytes_read res;}return 0; }json_object* receive_response() {char buffer[BUFFER_SIZE];uint32_t len;if (read_all(len, sizeof(len)) ! 0) return NULL;len ntohl(len);if (len BUFFER_SIZE) {fprintf(stderr, 服务器响应过大。\n);return NULL;}if (read_all(buffer, len) ! 0) return NULL;buffer[len] \0;return json_tokener_parse(buffer); }char* calculate_file_md5(const char *filepath) {unsigned char c[MD5_DIGEST_LENGTH];FILE *inFile fopen(filepath, rb);MD5_CTX mdContext;int bytes;unsigned char data[1024];static char md5_str[MD5_DIGEST_LENGTH * 2 1];if (inFile NULL) {printf(错误: 文件 %s 无法打开。\n, filepath);return NULL;}MD5_Init(mdContext);while ((bytes fread(data, 1, 1024, inFile)) ! 0) {MD5_Update(mdContext, data, bytes);}MD5_Final(c, mdContext);for (int i 0; i MD5_DIGEST_LENGTH; i) {sprintf(md5_str[i * 2], %02x, (unsigned int)c[i]);}md5_str[MD5_DIGEST_LENGTH * 2] \0;fclose(inFile);return md5_str; }int receive_file(const char *filepath, long long filesize) {FILE *fp fopen(filepath, wb);if (!fp) {perror(打开文件写入失败);return -1;}char buffer[BUFFER_SIZE];long long received_size 0;while (received_size filesize) {int bytes_to_read (filesize - received_size BUFFER_SIZE) ? (filesize - received_size) : BUFFER_SIZE;int bytes_read read(sock, buffer, bytes_to_read);if (bytes_read 0) {fclose(fp);return -1;}fwrite(buffer, 1, bytes_read, fp);received_size bytes_read;}fclose(fp);return 0; }int send_file(const char *filepath) {FILE *fp fopen(filepath, rb);if (!fp) return -1;char buffer[BUFFER_SIZE];size_t bytes_read;while ((bytes_read fread(buffer, 1, BUFFER_SIZE, fp)) 0) {if (write(sock, buffer, bytes_read) 0) {fclose(fp);return -1;}}fclose(fp);return 0; }void clear_stdin() {int c;while ((c getchar()) ! \n c ! EOF); }void pre_login_menu() {printf(\n 欢迎使用模拟网盘 \n);printf(1. 登录\n);printf(2. 注册\n);printf(0. 退出\n);printf(请输入您的选择: );int choice;if (scanf(%d, choice) ! 1) {clear_stdin();printf(无效输入请输入数字。\n);return;}clear_stdin();switch (choice) {case 1: handle_login(); break;case 2: handle_register(); break;case 0: safe_exit(0);default: printf(无效选择。\n);} }void post_login_menu() {const char* role is_admin ? 管理员 : (is_member ? 会员 : 普通用户);printf(\n 网盘菜单 (用户: %s, 身份: %s) \n, username, role);printf(1. 上传文件\n);printf(2. 下载文件\n);printf(3. 搜索服务器文件\n);printf(4. 查看我的上传\n);printf(5. 查看我的下载\n);printf(6. 管理我的上传和下载\n);printf(7. 注销我的账户\n);if (is_admin) {printf(------ 管理员面板 ------\n);printf(8. 设置/取消用户会员资格\n);printf(9. 删除用户账户\n);}printf(0. 登出\n);printf(请输入您的选择: );int choice;if (scanf(%d, choice) ! 1) {clear_stdin();printf(无效输入请输入数字。\n);return;}clear_stdin();switch (choice) {case 1: handle_upload(); break;case 2: handle_download(); break;case 3: handle_search(); break;case 4: handle_view_history(upload); break;case 5: handle_view_history(download); break;case 6: handle_delete_history(); break;case 7: handle_delete_account(); break;case 0: handle_logout(); break;default:if (is_admin (choice 8 || choice 9)) {if (choice 8) handle_admin_set_member();else handle_admin_delete_user();} else {printf(无效选择。\n);}} }void handle_register() {char reg_user[50], reg_pass[50];printf(请输入注册用户名: );scanf(%49s, reg_user);printf(请输入密码: );scanf(%49s, reg_pass);clear_stdin();json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(REGISTER));json_object_object_add(req, username, json_object_new_string(reg_user));json_object_object_add(req, password, json_object_new_string(reg_pass));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); safe_exit(1); }printf(服务器响应: %s\n, json_object_get_string(json_object_object_get(resp, message)));json_object_put(resp);json_object_put(req); }void handle_login() {char login_user[50], login_pass[50];printf(请输入用户名: );scanf(%49s, login_user);printf(请输入密码: );scanf(%49s, login_pass);clear_stdin();json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(LOGIN));json_object_object_add(req, username, json_object_new_string(login_user));json_object_object_add(req, password, json_object_new_string(login_pass));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); safe_exit(1); }const char *status json_object_get_string(json_object_object_get(resp, status));if (strcmp(status, SUCCESS) 0) {is_logged_in 1;user_id json_object_get_int(json_object_object_get(resp, user_id));is_admin json_object_get_int(json_object_object_get(resp, is_admin));is_member json_object_get_int(json_object_object_get(resp, is_member));strcpy(username, json_object_get_string(json_object_object_get(resp, username)));printf(登录成功。欢迎您, %s!\n, username);} else {printf(登录失败: %s\n, json_object_get_string(json_object_object_get(resp, message)));}json_object_put(resp);json_object_put(req); }void handle_logout() {is_logged_in 0; is_admin 0; is_member 0; user_id -1;memset(username, 0, sizeof(username));printf(您已成功登出。\n); }void handle_upload() {char filepath[256];printf(请输入要上传文件的绝对路径或相对路径: );scanf(%255s, filepath);clear_stdin();struct stat file_stat;if (stat(filepath, file_stat) 0) {perror(无法获取文件状态请检查文件路径是否正确);return;}char *md5 calculate_file_md5(filepath);if (!md5) return;char *fname basename(filepath);json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(UPLOAD));json_object_object_add(req, filename, json_object_new_string(fname));json_object_object_add(req, filesize, json_object_new_int64(file_stat.st_size));json_object_object_add(req, md5, json_object_new_string(md5));send_request(req);json_object_put(req);json_object *resp1 receive_response();if (!resp1) { printf(与服务器断开连接。\n); safe_exit(1); }const char *status json_object_get_string(json_object_object_get(resp1, status));const char *message json_object_get_string(json_object_object_get(resp1, message));printf(服务器响应: %s\n, message);if (strcmp(status, PROCEED_UPLOAD) 0) {printf(服务器准备就绪开始文件传输...\n);if (send_file(filepath) 0) {printf(文件数据已发送等待服务器最终确认...\n);json_object *resp2 receive_response();if (resp2) {printf(最终服务器响应: %s\n, json_object_get_string(json_object_object_get(resp2, message)));json_object_put(resp2);} else {printf(在最终确认阶段与服务器断开连接。\n);json_object_put(resp1);safe_exit(1);}} else {printf(文件传输失败。\n);}}json_object_put(resp1); }void handle_download() {char filename[256];printf(请输入要下载的文件名: );scanf(%255s, filename);clear_stdin();json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(DOWNLOAD));json_object_object_add(req, filename, json_object_new_string(filename));send_request(req);json_object_put(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); safe_exit(1); }const char *status json_object_get_string(json_object_object_get(resp, status));const char *message json_object_get_string(json_object_object_get(resp, message));printf(服务器响应: %s\n, message);if (strcmp(status, PROCEED_DOWNLOAD) 0) {long long filesize json_object_get_int64(json_object_object_get(resp, filesize));char save_path[512];sprintf(save_path, %s/%s, STORAGE_DIR, filename);printf(正在下载文件到 %s (大小: %lld 字节)...\n, save_path, filesize);if (receive_file(save_path, filesize) 0) {printf(下载完成\n);} else {printf(下载失败连接中断。\n);remove(save_path);}}json_object_put(resp); }void handle_search() {char keyword[100];printf(请输入要搜索的文件名关键字: );scanf(%99s, keyword);clear_stdin();json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(SEARCH));json_object_object_add(req, keyword, json_object_new_string(keyword));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); json_object_put(req); safe_exit(1); }json_object *data json_object_object_get(resp, data);int count json_object_array_length(data);printf(\n--- 搜索结果 (共 %d 条) ---\n, count);printf(%-30s | %-15s | %s\n, 文件名, 大小 (字节), 下载次数);printf(----------------------------------------------------------\n);for (int i 0; i count; i) {json_object *row json_object_array_get_idx(data, i);printf(%-30s | %-15s | %s\n,json_object_get_string(json_object_object_get(row, filename)),json_object_get_string(json_object_object_get(row, filesize)),json_object_get_string(json_object_object_get(row, download_count)));}printf(----------------------------------------------------------\n);json_object_put(resp);json_object_put(req); }void handle_view_history(const char* type) {json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(VIEW_HISTORY));json_object_object_add(req, type, json_object_new_string(type));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); json_object_put(req); safe_exit(1); }const char* type_cn strcmp(type, upload) 0 ? 上传 : 下载;json_object *data json_object_object_get(resp, data);int count json_object_array_length(data);printf(\n--- 我的%s记录 (共 %d 条) ---\n, type_cn, count);printf(%-5s | %-30s | %-15s | %s\n, ID, 文件名, 大小 (字节), 时间);printf(----------------------------------------------------------------------\n);for (int i 0; i count; i) {json_object *row json_object_array_get_idx(data, i);printf(%-5s | %-30s | %-15s | %s\n,json_object_get_string(json_object_object_get(row, id)),json_object_get_string(json_object_object_get(row, filename)),json_object_get_string(json_object_object_get(row, filesize)),json_object_get_string(json_object_object_get(row, (strcmp(type, upload) 0 ? upload_time : download_time))));}printf(----------------------------------------------------------------------\n);json_object_put(resp);json_object_put(req); }// **重大修改**: handle_delete_history void handle_delete_history() {char type_str[10];int record_id;printf(要管理哪种历史记录 (upload/download)? );scanf(%9s, type_str);clear_stdin();if (strcmp(type_str, upload) ! 0 strcmp(type_str, download) ! 0) {printf(类型无效必须是 upload 或 download。\n);return;}printf(请输入要删除的记录ID或输入-1删除全部: );if (scanf(%d, record_id) ! 1) {clear_stdin();printf(无效输入请输入数字。\n);return;}clear_stdin();json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(DELETE_HISTORY));json_object_object_add(req, type, json_object_new_string(type_str));json_object_object_add(req, record_id, json_object_new_int(record_id));send_request(req);json_object_put(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); safe_exit(1); }printf(服务器响应: %s\n, json_object_get_string(json_object_object_get(resp, message)));// **新增逻辑**: 检查是否需要删除本地文件json_object *deleted_filename_obj;if (json_object_object_get_ex(resp, deleted_filename, deleted_filename_obj)) {const char *deleted_filename json_object_get_string(deleted_filename_obj);printf(是否同时删除本地文件 %s? (y/n): , deleted_filename);char choice;scanf( %c, choice);clear_stdin();if (choice y || choice Y) {char local_filepath[512];sprintf(local_filepath, %s/%s, STORAGE_DIR, deleted_filename);if (remove(local_filepath) 0) {printf(本地文件 %s 删除成功。\n, deleted_filename);} else {perror(删除本地文件失败);}} else {printf(已保留本地文件。\n);}}json_object_put(resp); }void handle_delete_account() {char confirmation[10];printf(您确定要永久删除您的账户吗此操作无法撤销。\n);printf(请输入 YES 确认: );scanf(%9s, confirmation);clear_stdin();if (strcmp(confirmation, YES) ! 0) {printf(账户删除已取消。\n);return;}json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(DELETE_ACCOUNT));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); json_object_put(req); safe_exit(1); }printf(服务器响应: %s\n, json_object_get_string(json_object_object_get(resp, message)));if (strcmp(json_object_get_string(json_object_object_get(resp, status)), SUCCESS) 0) {handle_logout();printf(您将被返回到主菜单。\n);}json_object_put(resp);json_object_put(req); }void handle_admin_set_member() {char target_user[50];int status;printf(请输入要修改的用户名: );scanf(%49s, target_user);printf(是否设为会员? (1 为是, 0 为否): );if (scanf(%d, status) ! 1) {clear_stdin();printf(无效输入请输入数字。\n);return;}clear_stdin();json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(ADMIN_SET_MEMBER));json_object_object_add(req, target_user, json_object_new_string(target_user));json_object_object_add(req, is_member, json_object_new_int(status));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); json_object_put(req); safe_exit(1); }printf(服务器响应: %s\n, json_object_get_string(json_object_object_get(resp, message)));json_object_put(resp);json_object_put(req); }void handle_admin_delete_user() {char target_user[50];printf(请输入要删除的用户名: );scanf(%49s, target_user);clear_stdin();char confirmation[10];printf(警告: 这将永久删除用户 %s 及其所有数据。请输入 DELETE 确认: , target_user);scanf(%9s, confirmation);clear_stdin();if (strcmp(confirmation, DELETE) ! 0) {printf(删除用户操作已取消。\n);return;}json_object *req json_object_new_object();json_object_object_add(req, command, json_object_new_string(ADMIN_DELETE_USER));json_object_object_add(req, target_user, json_object_new_string(target_user));send_request(req);json_object *resp receive_response();if (!resp) { printf(与服务器断开连接。\n); json_object_put(req); safe_exit(1); }printf(服务器响应: %s\n, json_object_get_string(json_object_object_get(resp, message)));json_object_put(resp);json_object_put(req); }init_db.c #include stdio.h #include sqlite3.h #include stdlib.hint main() {sqlite3 *db;char *err_msg 0;// 1. 打开如果不存在则创建数据库文件int rc sqlite3_open(db, db);if (rc ! SQLITE_OK) {fprintf(stderr, 无法打开数据库: %s\n, sqlite3_errmsg(db));sqlite3_close(db);return 1;}printf(数据库打开成功。\n);// 2. 创建用户表 (users)const char *sql_create_users CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL UNIQUE, password TEXT NOT NULL, is_admin INTEGER NOT NULL DEFAULT 0, is_member INTEGER NOT NULL DEFAULT 0, register_time DATETIME DEFAULT CURRENT_TIMESTAMP);;rc sqlite3_exec(db, sql_create_users, 0, 0, err_msg);if (rc ! SQLITE_OK) {fprintf(stderr, SQL错误 (users): %s\n, err_msg);sqlite3_free(err_msg);sqlite3_close(db);return 1;}printf(用户表 users 创建成功。\n);// 3. 创建服务端文件信息表 (server_files)const char *sql_create_server_files CREATE TABLE IF NOT EXISTS server_files (id INTEGER PRIMARY KEY AUTOINCREMENT, filename TEXT NOT NULL, filesize INTEGER NOT NULL, md5 TEXT NOT NULL UNIQUE, upload_time DATETIME DEFAULT CURRENT_TIMESTAMP, download_count INTEGER DEFAULT 0);;rc sqlite3_exec(db, sql_create_server_files, 0, 0, err_msg);if (rc ! SQLITE_OK) {fprintf(stderr, SQL错误 (server_files): %s\n, err_msg);sqlite3_free(err_msg);sqlite3_close(db);return 1;}printf(文件信息表 server_files 创建成功。\n);// 4. 添加默认管理员账户 (admin/admin)sqlite3_stmt *stmt;const char *sql_check_admin SELECT id FROM users WHERE username admin;;rc sqlite3_prepare_v2(db, sql_check_admin, -1, stmt, 0);if (rc ! SQLITE_OK) {fprintf(stderr, 预处理语句失败: %s\n, sqlite3_errmsg(db));sqlite3_close(db);return 1;}if (sqlite3_step(stmt) ! SQLITE_ROW) { // 管理员不存在const char *sql_insert_admin INSERT INTO users (username, password, is_admin, is_member) VALUES (admin, admin, 1, 1);;rc sqlite3_exec(db, sql_insert_admin, 0, 0, err_msg);if (rc ! SQLITE_OK) {fprintf(stderr, SQL错误 (插入管理员): %s\n, err_msg);sqlite3_free(err_msg);} else {printf(默认管理员账户 admin/admin 创建成功。\n);}} else {printf(管理员账户已存在。\n);}sqlite3_finalize(stmt);// 5. 关闭数据库sqlite3_close(db);printf(数据库初始化完成。\n);return 0; }server.c #include stdio.h #include stdlib.h #include string.h #include unistd.h #include arpa/inet.h #include sys/socket.h #include pthread.h #include sqlite3.h #include json-c/json.h #include openssl/md5.h #include sys/stat.h #include dirent.h#define BUFFER_SIZE 4096 #define PORT 8888 #define MAX_CLIENTS 30 #define STORAGE_DIR server_storage #define MEMBER_LIMIT 20480 // 20KB// 全局变量 sqlite3 *db; pthread_mutex_t db_mutex; pthread_mutex_t clients_mutex;// 客户端信息结构 typedef struct {int sock;struct sockaddr_in address;int user_id;char username[50];int is_logged_in;int is_admin;int is_member; } client_t;client_t *clients[MAX_CLIENTS];// 函数声明 void add_client(client_t *cl); void remove_client(int sock); void print_connected_clients(); char* calculate_file_md5(const char *filepath); void handle_client(void *arg); json_object* process_request(json_object *req, client_t *client_info);// 主函数 int main() {mkdir(STORAGE_DIR, 0777);if (sqlite3_open(db, db)) {fprintf(stderr, 无法打开数据库: %s\n, sqlite3_errmsg(db));return 1;} else {fprintf(stdout, 数据库打开成功\n);}pthread_mutex_init(db_mutex, NULL);pthread_mutex_init(clients_mutex, NULL);int server_sock, client_sock;struct sockaddr_in server_addr, client_addr;socklen_t client_addr_len sizeof(client_addr);pthread_t tid;server_sock socket(AF_INET, SOCK_STREAM, 0);if (server_sock -1) {perror(无法创建套接字);return 1;}int opt 1;if (setsockopt(server_sock, SOL_SOCKET, SO_REUSEADDR, opt, sizeof(opt)) 0) {perror(setsockopt(SO_REUSEADDR) 失败);exit(EXIT_FAILURE);}server_addr.sin_family AF_INET;server_addr.sin_addr.s_addr INADDR_ANY;server_addr.sin_port htons(PORT);if (bind(server_sock, (struct sockaddr *)server_addr, sizeof(server_addr)) 0) {perror(绑定失败);close(server_sock);return 1;}printf(服务器绑定成功\n);listen(server_sock, 5);printf(服务器正在监听端口 %d...\n, PORT);printf(等待客户端连接...\n);while (1) {client_sock accept(server_sock, (struct sockaddr *)client_addr, client_addr_len);if (client_sock 0) {perror(接受连接失败);continue;}printf(接受来自 %s:%d 的连接\n, inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));client_t *cli (client_t *)malloc(sizeof(client_t));cli-address client_addr;cli-sock client_sock;cli-user_id -1;cli-is_logged_in 0;cli-is_admin 0;cli-is_member 0;memset(cli-username, 0, sizeof(cli-username));add_client(cli);if (pthread_create(tid, NULL, (void *)handle_client, (void *)cli) 0) {perror(无法创建线程);free(cli);close(client_sock);}}close(server_sock);sqlite3_close(db);pthread_mutex_destroy(db_mutex);pthread_mutex_destroy(clients_mutex);return 0; }void add_client(client_t *cl) {pthread_mutex_lock(clients_mutex);for (int i 0; i MAX_CLIENTS; i) {if (!clients[i]) {clients[i] cl;break;}}pthread_mutex_unlock(clients_mutex); }void remove_client(int sock) {pthread_mutex_lock(clients_mutex);for (int i 0; i MAX_CLIENTS; i) {if (clients[i] clients[i]-sock sock) {printf(客户端断开连接: %s (套接字: %d)\n, clients[i]-is_logged_in ? clients[i]-username : 未登录, sock);free(clients[i]);clients[i] NULL;break;}}pthread_mutex_unlock(clients_mutex);print_connected_clients(); }void print_connected_clients() {pthread_mutex_lock(clients_mutex);printf(\n--- 当前在线客户端 ---\n);int count 0;for (int i 0; i MAX_CLIENTS; i) {if (clients[i] clients[i]-is_logged_in) {const char* role clients[i]-is_admin ? 管理员 : (clients[i]-is_member ? 会员 : 普通用户);printf( - %s (用户ID: %d, 身份: %s)\n, clients[i]-username, clients[i]-user_id, role);count;}}if (count 0) {printf( 无已登录的客户端。\n);}printf(----------------------\n);pthread_mutex_unlock(clients_mutex); }char* calculate_file_md5(const char *filepath) {unsigned char c[MD5_DIGEST_LENGTH];FILE *inFile fopen(filepath, rb);MD5_CTX mdContext;int bytes;unsigned char data[1024];char *md5_str (char*)malloc(MD5_DIGEST_LENGTH * 2 1);if (md5_str NULL) {fprintf(stderr, 为MD5字符串分配内存失败\n);if (inFile) fclose(inFile);return NULL;}if (inFile NULL) {fprintf(stderr, 文件 %s 无法打开。\n, filepath);free(md5_str);return NULL;}MD5_Init(mdContext);while ((bytes fread(data, 1, 1024, inFile)) ! 0) {MD5_Update(mdContext, data, bytes);}MD5_Final(c, mdContext);for (int i 0; i MD5_DIGEST_LENGTH; i) {sprintf(md5_str[i * 2], %02x, (unsigned int)c[i]);}md5_str[MD5_DIGEST_LENGTH * 2] \0;fclose(inFile);return md5_str; }void send_response(int sock, json_object *response) {const char *response_str json_object_to_json_string(response);uint32_t len htonl(strlen(response_str));write(sock, len, sizeof(len));write(sock, response_str, strlen(response_str)); }int read_all(int sock, void *buf, size_t len) {size_t bytes_read 0;while (bytes_read len) {ssize_t res read(sock, (char*)buf bytes_read, len - bytes_read);if (res 0) return -1;bytes_read res;}return 0; }int receive_file(int sock, const char *filepath, long long filesize) {FILE *fp fopen(filepath, wb);if (!fp) {perror(打开文件写入失败);return -1;}char buffer[BUFFER_SIZE];long long received_size 0;while (received_size filesize) {int bytes_to_read (filesize - received_size BUFFER_SIZE) ? (filesize - received_size) : BUFFER_SIZE;int bytes_read read(sock, buffer, bytes_to_read);if (bytes_read 0) {fclose(fp);return -1;}fwrite(buffer, 1, bytes_read, fp);received_size bytes_read;}fclose(fp);return 0; }int send_file(int sock, const char *filepath) {FILE *fp fopen(filepath, rb);if (!fp) return -1;char buffer[BUFFER_SIZE];size_t bytes_read;while ((bytes_read fread(buffer, 1, BUFFER_SIZE, fp)) 0) {if (write(sock, buffer, bytes_read) 0) {fclose(fp);return -1;}}fclose(fp);return 0; }static int single_value_callback(void *data, int argc, char **argv, char **azColName) {if (argc 0 argv[0]) strcpy((char *)data, argv[0]);return 0; }void record_user_upload(int user_id, const char* filename, long long filesize) {char user_upload_table[100];sprintf(user_upload_table, user_uploads_%d, user_id);char create_table_sql[256];sprintf(create_table_sql, CREATE TABLE IF NOT EXISTS %s (id INTEGER PRIMARY KEY AUTOINCREMENT, filename TEXT, filesize INTEGER, upload_time DATETIME DEFAULT CURRENT_TIMESTAMP);, user_upload_table);char insert_sql[1024];sprintf(insert_sql, INSERT INTO %s (filename, filesize) VALUES (%s, %lld);, user_upload_table, filename, filesize);sqlite3_exec(db, create_table_sql, 0, 0, NULL);sqlite3_exec(db, insert_sql, 0, 0, NULL); }void do_register(json_object *req, json_object *resp) {const char *username json_object_get_string(json_object_object_get(req, username));const char *password json_object_get_string(json_object_object_get(req, password));char sql[256], *err_msg 0;sprintf(sql, INSERT INTO users (username, password) VALUES (%s, %s);, username, password);pthread_mutex_lock(db_mutex);int rc sqlite3_exec(db, sql, 0, 0, err_msg);pthread_mutex_unlock(db_mutex);if (rc ! SQLITE_OK) {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(用户名已存在或数据库错误。));sqlite3_free(err_msg);} else {json_object_object_add(resp, status, json_object_new_string(SUCCESS));json_object_object_add(resp, message, json_object_new_string(注册成功。));} }void do_login(json_object *req, json_object *resp, client_t *client_info) {const char *username json_object_get_string(json_object_object_get(req, username));const char *password json_object_get_string(json_object_object_get(req, password));char sql[512];sqlite3_stmt *stmt;sprintf(sql, SELECT id, is_admin, is_member FROM users WHERE username ? AND password ?;);pthread_mutex_lock(db_mutex);int rc sqlite3_prepare_v2(db, sql, -1, stmt, 0);if (rc SQLITE_OK) {sqlite3_bind_text(stmt, 1, username, -1, SQLITE_STATIC);sqlite3_bind_text(stmt, 2, password, -1, SQLITE_STATIC);if (sqlite3_step(stmt) SQLITE_ROW) {client_info-user_id sqlite3_column_int(stmt, 0);strcpy(client_info-username, username);client_info-is_logged_in 1;client_info-is_admin sqlite3_column_int(stmt, 1);client_info-is_member sqlite3_column_int(stmt, 2);json_object_object_add(resp, status, json_object_new_string(SUCCESS));json_object_object_add(resp, message, json_object_new_string(登录成功。));json_object_object_add(resp, user_id, json_object_new_int(client_info-user_id));json_object_object_add(resp, username, json_object_new_string(client_info-username));json_object_object_add(resp, is_admin, json_object_new_int(client_info-is_admin));json_object_object_add(resp, is_member, json_object_new_int(client_info-is_member));print_connected_clients();} else {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(用户名不存在或密码错误。));}} else {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(数据库查询失败。));}sqlite3_finalize(stmt);pthread_mutex_unlock(db_mutex); }void do_upload(json_object *req, json_object *resp, client_t *client_info) {const char *filename json_object_get_string(json_object_object_get(req, filename));long long filesize json_object_get_int64(json_object_object_get(req, filesize));const char *md5_from_client json_object_get_string(json_object_object_get(req, md5));if (!client_info-is_member filesize MEMBER_LIMIT) {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(权限不足普通用户上传文件大小不能超过20KB。));return;}char sql[512];sqlite3_stmt *stmt;sprintf(sql, SELECT filename FROM server_files WHERE md5 ?;);pthread_mutex_lock(db_mutex);int rc sqlite3_prepare_v2(db, sql, -1, stmt, 0);sqlite3_bind_text(stmt, 1, md5_from_client, -1, SQLITE_STATIC);if (rc SQLITE_OK sqlite3_step(stmt) SQLITE_ROW) {sqlite3_finalize(stmt);record_user_upload(client_info-user_id, filename, filesize);pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(SUCCESS_SECONDUPLOAD));json_object_object_add(resp, message, json_object_new_string(文件已存在于服务器秒传成功。));return;}sqlite3_finalize(stmt);pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(PROCEED_UPLOAD));json_object_object_add(resp, message, json_object_new_string(服务器准备就绪请开始上传文件。)); }void do_download(json_object *req, json_object *resp, client_t *client_info) {const char* filename json_object_get_string(json_object_object_get(req, filename));char filepath[512];sprintf(filepath, %s/%s, STORAGE_DIR, filename);struct stat file_stat;if (stat(filepath, file_stat) 0) {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(文件在服务器上不存在。));return;}long long filesize file_stat.st_size;if (!client_info-is_member filesize MEMBER_LIMIT) {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(权限不足普通用户下载文件大小不能超过20KB。));return;}json_object_object_add(resp, status, json_object_new_string(PROCEED_DOWNLOAD));json_object_object_add(resp, message, json_object_new_string(文件找到开始下载。));json_object_object_add(resp, filesize, json_object_new_int64(filesize)); }struct query_result { json_object *jarray; }; static int query_to_json_callback(void *data, int argc, char **argv, char **azColName) {struct query_result *res (struct query_result *)data;json_object *jrow json_object_new_object();for (int i 0; i argc; i) {json_object_object_add(jrow, azColName[i], json_object_new_string(argv[i] ? argv[i] : NULL));}json_object_array_add(res-jarray, jrow);return 0; }void do_search(json_object *req, json_object *resp) {const char* keyword json_object_get_string(json_object_object_get(req, keyword));char sql[512];sprintf(sql, SELECT filename, filesize, download_count FROM server_files WHERE filename LIKE %%%s%%;, keyword);struct query_result res;res.jarray json_object_new_array();pthread_mutex_lock(db_mutex);sqlite3_exec(db, sql, query_to_json_callback, res, NULL);pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(SUCCESS));json_object_object_add(resp, data, res.jarray); }void do_view_history(json_object *req, json_object *resp, client_t *client_info) {const char *type json_object_get_string(json_object_object_get(req, type));char table_name[100];sprintf(table_name, user_%ss_%d, type, client_info-user_id);char sql[512];sprintf(sql, SELECT id, filename, filesize, %s_time FROM %s;, type, table_name);struct query_result res { .jarray json_object_new_array() };pthread_mutex_lock(db_mutex);char check_sql[256];sqlite3_stmt *stmt;sprintf(check_sql, SELECT name FROM sqlite_master WHERE typetable AND name%s;, table_name);if (sqlite3_prepare_v2(db, check_sql, -1, stmt, 0) SQLITE_OK) {if (sqlite3_step(stmt) SQLITE_ROW) {sqlite3_exec(db, sql, query_to_json_callback, res, NULL);}sqlite3_finalize(stmt);}pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(SUCCESS));json_object_object_add(resp, data, res.jarray); }// **重大修改**: do_delete_history void do_delete_history(json_object *req, json_object *resp, client_t *client_info) {const char *type json_object_get_string(json_object_object_get(req, type));int record_id json_object_get_int(json_object_object_get(req, record_id));char table_name[100];sprintf(table_name, user_%ss_%d, type, client_info-user_id);char sql[256];pthread_mutex_lock(db_mutex);if (record_id ! -1 strcmp(type, download) 0) {// 如果是删除单条下载记录先查询出文件名char filename_buf[256] {0};sprintf(sql, SELECT filename FROM %s WHERE id %d;, table_name, record_id);sqlite3_exec(db, sql, single_value_callback, filename_buf, NULL);if (strlen(filename_buf) 0) {json_object_object_add(resp, deleted_filename, json_object_new_string(filename_buf));}}if (record_id -1) { // 删除全部sprintf(sql, DELETE FROM %s;, table_name);} else { // 删除单条sprintf(sql, DELETE FROM %s WHERE id %d;, table_name, record_id);}sqlite3_exec(db, sql, 0, 0, NULL);pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(SUCCESS));json_object_object_add(resp, message, json_object_new_string(历史记录已删除。)); }void do_delete_account(json_object *resp, client_t *client_info) {char sql[512], table_name[100];pthread_mutex_lock(db_mutex);sprintf(sql, DELETE FROM users WHERE id %d;, client_info-user_id);sqlite3_exec(db, sql, 0, 0, NULL);sprintf(table_name, user_uploads_%d, client_info-user_id);sprintf(sql, DROP TABLE IF EXISTS %s;, table_name);sqlite3_exec(db, sql, 0, 0, NULL);sprintf(table_name, user_downloads_%d, client_info-user_id);sprintf(sql, DROP TABLE IF EXISTS %s;, table_name);sqlite3_exec(db, sql, 0, 0, NULL);pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(SUCCESS));json_object_object_add(resp, message, json_object_new_string(您的账户已成功删除。)); }void do_admin_set_member(json_object *req, json_object *resp) {const char *target_user json_object_get_string(json_object_object_get(req, target_user));int is_member json_object_get_int(json_object_object_get(req, is_member));char sql[256];sprintf(sql, UPDATE users SET is_member %d WHERE username %s;, is_member, target_user);pthread_mutex_lock(db_mutex);sqlite3_exec(db, sql, 0, 0, NULL);int changes sqlite3_changes(db);pthread_mutex_unlock(db_mutex);if (changes 0) {json_object_object_add(resp, status, json_object_new_string(SUCCESS));char msg[128];sprintf(msg, 用户 %s 的会员状态已更新。, target_user);json_object_object_add(resp, message, json_object_new_string(msg));} else {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(未找到该用户。));} }void do_admin_delete_user(json_object *req, json_object *resp) {const char *target_user json_object_get_string(json_object_object_get(req, target_user));if (strcmp(target_user, admin) 0) {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(不能删除管理员账户。));return;}char sql[512], target_id_str[20] {0};pthread_mutex_lock(db_mutex);sprintf(sql, SELECT id FROM users WHERE username %s;, target_user);sqlite3_exec(db, sql, single_value_callback, target_id_str, NULL);if (strlen(target_id_str) 0) {pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(未找到该用户。));return;}int target_id atoi(target_id_str);sprintf(sql, DELETE FROM users WHERE id %d;, target_id);sqlite3_exec(db, sql, 0, 0, NULL);char table_name[100];sprintf(table_name, user_uploads_%d, target_id);sprintf(sql, DROP TABLE IF EXISTS %s;, table_name);sqlite3_exec(db, sql, 0, 0, NULL);sprintf(table_name, user_downloads_%d, target_id);sprintf(sql, DROP TABLE IF EXISTS %s;, table_name);sqlite3_exec(db, sql, 0, 0, NULL);pthread_mutex_unlock(db_mutex);json_object_object_add(resp, status, json_object_new_string(SUCCESS));char msg[128];sprintf(msg, 用户 %s 及其所有关联数据已被删除。, target_user);json_object_object_add(resp, message, json_object_new_string(msg)); }json_object* process_request(json_object *req, client_t *client_info) {json_object *resp json_object_new_object();const char *command json_object_get_string(json_object_object_get(req, command));if (strcmp(command, REGISTER) 0) { do_register(req, resp); } else if (strcmp(command, LOGIN) 0) { do_login(req, resp, client_info); } else if (client_info-is_logged_in) {if (strcmp(command, UPLOAD) 0) { do_upload(req, resp, client_info); } else if (strcmp(command, DOWNLOAD) 0) { do_download(req, resp, client_info); } else if (strcmp(command, SEARCH) 0) { do_search(req, resp); } else if (strcmp(command, VIEW_HISTORY) 0) { do_view_history(req, resp, client_info); } else if (strcmp(command, DELETE_HISTORY) 0) { do_delete_history(req, resp, client_info); } else if (strcmp(command, DELETE_ACCOUNT) 0) { do_delete_account(resp, client_info); } else if (client_info-is_admin) {if (strcmp(command, ADMIN_SET_MEMBER) 0) { do_admin_set_member(req, resp); } else if (strcmp(command, ADMIN_DELETE_USER) 0) { do_admin_delete_user(req, resp); }else {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(未知管理员命令。));}} else {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(未知命令或权限不足。));}} else {json_object_object_add(resp, status, json_object_new_string(ERROR));json_object_object_add(resp, message, json_object_new_string(需要认证请先登录。));}return resp; }void handle_client(void *arg) {client_t *cli (client_t *)arg;char buffer[BUFFER_SIZE];while (1) {uint32_t len;if (read_all(cli-sock, len, sizeof(len)) ! 0) break;len ntohl(len);if (len BUFFER_SIZE) {fprintf(stderr, 来自套接字 %d 的请求过大断开连接。\n, cli-sock);break;}if (read_all(cli-sock, buffer, len) ! 0) break;buffer[len] \0;json_object *req json_tokener_parse(buffer);if (!req) {fprintf(stderr, 来自套接字 %d 的JSON无效断开连接。\n, cli-sock);break;}json_object *resp process_request(req, cli);const char *cmd json_object_get_string(json_object_object_get(req, command));const char *status_str json_object_get_string(json_object_object_get(resp, status));send_response(cli-sock, resp);if (status_str strcmp(status_str, PROCEED_UPLOAD) 0) {const char *filename json_object_get_string(json_object_object_get(req, filename));long long filesize json_object_get_int64(json_object_object_get(req, filesize));const char *md5_from_client json_object_get_string(json_object_object_get(req, md5));char temp_filepath[512];sprintf(temp_filepath, %s/%s.tmp, STORAGE_DIR, filename);if (receive_file(cli-sock, temp_filepath, filesize) ! 0) {fprintf(stderr, 接收文件 %s 失败\n, filename);remove(temp_filepath);} else {char *received_md5 calculate_file_md5(temp_filepath);json_object *final_resp json_object_new_object();if (received_md5 strcmp(received_md5, md5_from_client) 0) {char final_filepath[512];sprintf(final_filepath, %s/%s, STORAGE_DIR, filename);rename(temp_filepath, final_filepath);pthread_mutex_lock(db_mutex);char sql[512];sprintf(sql, INSERT OR IGNORE INTO server_files (filename, filesize, md5) VALUES (%s, %lld, %s);, filename, filesize, received_md5);sqlite3_exec(db, sql, 0, 0, NULL);record_user_upload(cli-user_id, filename, filesize);pthread_mutex_unlock(db_mutex);json_object_object_add(final_resp, status, json_object_new_string(SUCCESS));json_object_object_add(final_resp, message, json_object_new_string(文件上传并校验成功。));} else {remove(temp_filepath);json_object_object_add(final_resp, status, json_object_new_string(ERROR));json_object_object_add(final_resp, message, json_object_new_string(文件传输错误MD5校验不匹配请重新上传。));}if (received_md5) free(received_md5);send_response(cli-sock, final_resp);json_object_put(final_resp);}} else if (status_str strcmp(status_str, PROCEED_DOWNLOAD) 0) {const char* filename json_object_get_string(json_object_object_get(req, filename));long long filesize json_object_get_int64(json_object_object_get(resp, filesize));char filepath[512];sprintf(filepath, %s/%s, STORAGE_DIR, filename);if (send_file(cli-sock, filepath) 0) {pthread_mutex_lock(db_mutex);char sql[512];sprintf(sql, UPDATE server_files SET download_count download_count 1 WHERE filename %s;, filename);sqlite3_exec(db, sql, 0, 0, NULL);char user_download_table[100];sprintf(user_download_table, user_downloads_%d, cli-user_id);char create_table_sql[256];sprintf(create_table_sql, CREATE TABLE IF NOT EXISTS %s (id INTEGER PRIMARY KEY AUTOINCREMENT, filename TEXT, filesize INTEGER, download_time DATETIME DEFAULT CURRENT_TIMESTAMP);, user_download_table);sqlite3_exec(db, create_table_sql, 0, 0, NULL);sprintf(sql, INSERT INTO %s (filename, filesize) VALUES (%s, %lld);, user_download_table, filename, filesize);sqlite3_exec(db, sql, 0, 0, NULL);pthread_mutex_unlock(db_mutex);} else {fprintf(stderr, 发送文件 %s 到客户端 %s 失败\n, filename, cli-username);}}if (status_str strcmp(cmd, DELETE_ACCOUNT) 0 strcmp(status_str, SUCCESS) 0) {json_object_put(req);json_object_put(resp);break; }json_object_put(req);json_object_put(resp);}close(cli-sock);remove_client(cli-sock);pthread_detach(pthread_self()); }Makefile # Makefile for the Simulated Network Disk Project# Compiler and flags CC gcc CFLAGS -Wall -g # -Wall enables all warnings, -g adds debug info LDFLAGS_SERVER -lsqlite3 -lpthread -ljson-c -lcrypto LDFLAGS_CLIENT -ljson-c -lcrypto -lpthread LDFLAGS_INITDB -lsqlite3# Executable names SERVER_EXEC server CLIENT_EXEC client INITDB_EXEC init_db# Source files SERVER_SRC server.c CLIENT_SRC client.c INITDB_SRC init_db.c# Phony targets .PHONY: all clean# Default target all: $(SERVER_EXEC) $(CLIENT_EXEC) $(INITDB_EXEC)# Rule to build the server $(SERVER_EXEC): $(SERVER_SRC)$(CC) $(CFLAGS) -o $ $^ $(LDFLAGS_SERVER)# Rule to build the client $(CLIENT_EXEC): $(CLIENT_SRC)$(CC) $(CFLAGS) -o $ $^ $(LDFLAGS_CLIENT)# Rule to build the database initializer $(INITDB_EXEC): $(INITDB_SRC)$(CC) $(CFLAGS) -o $ $^ $(LDFLAGS_INITDB)# Clean up build artifacts clean:rm -f $(SERVER_EXEC) $(CLIENT_EXEC) $(INITDB_EXEC) *.o详细使用方法 1. 环境准备 首先确保系统已安装所有依赖库 # 一键安装所有依赖Ubuntu/Debian sudo apt-get update sudo apt-get install build-essential libpthread-stubs0-dev libjson-c-dev libssl-dev libsqlite3-dev sqlite3# 一键安装所有依赖CentOS/RHEL sudo yum groupinstall Development Tools sudo yum install glibc-devel json-c-devel openssl-devel sqlite-devel sqlite2. 编译项目 项目提供了Makefile文件可以方便地编译所有组件 # 编译所有程序 make all# 或者分别编译 make server # 编译服务器端 make client # 编译客户端 make init_db # 编译数据库初始化程序# 清理编译文件 make clean3. 初始化数据库 首次使用前需要初始化数据库 ./init_db这将创建 用户表users服务器文件信息表server_files默认管理员账户用户名admin密码admin 4. 启动服务器 ./server服务器将在8888端口监听客户端连接。启动后会显示 数据库打开成功 服务器绑定成功 服务器正在监听端口 8888... 等待客户端连接...5. 启动客户端 在另一个终端窗口运行 ./client6. 使用流程示例 6.1 新用户注册欢迎使用模拟网盘 1. 登录 2. 注册 0. 退出 请输入您的选择: 2 请输入注册用户名: testuser 请输入密码: 123456 服务器响应: 注册成功。6.2 用户登录 请输入您的选择: 1 请输入用户名: testuser 请输入密码: 123456 登录成功。欢迎您, testuser!6.3 上传文件网盘菜单 (用户: testuser, 身份: 普通用户) 1. 上传文件 ... 请输入您的选择: 1 请输入要上传文件的绝对路径或相对路径: /home/user/test.txt 服务器响应: 服务器准备就绪请开始上传文件。 服务器准备就绪开始文件传输... 文件数据已发送等待服务器最终确认... 最终服务器响应: 文件上传并校验成功。6.4 管理员操作 使用admin账户登录后可以进行管理操作 ------ 管理员面板 ------ 8. 设置/取消用户会员资格 9. 删除用户账户7. 目录结构 运行后会自动创建以下目录 server_storage/ - 服务器端文件存储目录client_storage/ - 客户端下载文件存储目录db - SQLite数据库文件 8. 注意事项 端口配置默认使用8888端口如需修改请同时修改server.c和client.c中的PORT定义IP配置客户端默认连接127.0.0.1本地如需远程连接请修改client.c中的SERVER_IP文件大小限制普通用户限制为20KB可在server.c中的MEMBER_LIMIT修改并发连接数最大支持30个客户端可在server.c中的MAX_CLIENTS修改故障排除 1. 编译错误 确保所有依赖库已正确安装检查gcc版本是否支持C99标准 2. 连接失败 确保服务器已启动检查防火墙是否开放8888端口确认IP地址配置正确 3. 数据库错误 确保已运行init_db初始化数据库检查当前用户是否有读写db文件的权限总结 本项目实现了一个功能完整的简易云盘系统涵盖了网络编程、数据库操作、多线程并发、文件处理等多个Linux系统编程的核心技术。通过本项目的学习和实践可以深入理解 TCP Socket编程的原理和实践多线程并发服务器的设计与实现JSON数据交换格式的应用SQLite数据库的使用文件完整性校验和去重技术 文章到此结束啦如果觉得本文章对您有所帮助请点个赞和关注以及收藏你的支持就是我继续更新的最大动力谢谢
http://www.zqtcl.cn/news/244255/

相关文章:

  • 官方网站有哪些韶关做网站的公司
  • 商城网站设计公司怎么样网站制作预算
  • 在济南什么人想做网站网站建设后怎么做主页
  • 联合年检怎么做网站上国家备案查询
  • 社交网站wap模板wordpress网址导航插件
  • 沈阳快速建站公司有哪些国外做二手服装网站
  • 手机如何建立网站平台seo比较好的优化
  • 电商网站建设外包禅城南庄网站制作
  • 哈尔滨企业网站开发报价免费php网站源码
  • 东莞市公司网站建设淄博网站制作营销
  • 企业网站无线端怎么做手机网站做成app
  • 让他人建设网站需要提供的材料可在哪些网站做链接
  • 外贸公司做网站3d建模好学吗
  • dedecms新网站 上传到万网的空间上海新媒体运营公司排名
  • 包装东莞网站建设0769三层网络架构
  • 淘客网站自己做固安建站公司
  • 咸阳学校网站建设联系电话网络app开发网站建设价格
  • 没网站怎么做淘宝客网站建设耂首先金手指
  • 网站带做收录排名淘外网站怎么做
  • 网站建设分金手指排名五申请邮箱账号注册
  • 餐饮加盟网站建设字体怎么安装wordpress
  • 网站建设与维护培训凡科和有赞哪个好用
  • 景区网站的作用长春新冠最新情况
  • 个人网站上传有啥要求wordpress 浏览记录
  • appcan 手机网站开发wordpress首页音乐
  • 杭州响应式网站案例建筑工程网站建站方案
  • 网站访客抓取国内网站搭建
  • 凡科网站做的好不好太原网页
  • 十堰商城网站建设国外效果图网站
  • 怎么登陆建设工程网站泉州网红