网站开发背景意义用软件做模板下载网站
2026/4/18 10:46:11 网站建设 项目流程
网站开发背景意义,用软件做模板下载网站,空间站天宫vr全景,外链查询工具一、项目概述本文将介绍如何基于 C 语言实现一个简易的在线商城 Web 服务器#xff0c;该服务器具备用户注册、登录、商品搜索、商品详情展示等核心功能#xff0c;底层采用 SQLite3 数据库存储数据#xff0c;同时解决了 SQL 注入、URL 解码等常见 Web 开发问题#xff0c…一、项目概述本文将介绍如何基于 C 语言实现一个简易的在线商城 Web 服务器该服务器具备用户注册、登录、商品搜索、商品详情展示等核心功能底层采用 SQLite3 数据库存储数据同时解决了 SQL 注入、URL 解码等常见 Web 开发问题可作为轻量级在线商城的基础框架。技术栈编程语言C 语言网络编程SocketTCP/IP数据库SQLite3Web 协议HTTP/1.1其他文件 I/O、URL 解码、SQL 预处理语句二、核心功能实现1. 项目整体架构服务器采用经典的 TCP Socket 监听 - 连接模型端口绑定 80HTTP 默认端口主要处理 GET 请求核心流程创建监听 Socket 并设置端口复用循环接收客户端连接解析 HTTP 请求行提取请求方法和 URL根据 URL 路由到不同业务逻辑注册 / 登录 / 商品搜索 / 详情处理完成后返回 HTML / 图片等资源关闭连接2. 数据库基础操作SQLite3 是轻量级嵌入式数据库本项目使用预处理语句sqlite3_prepare_v2 绑定参数解决 SQL 注入问题核心封装了注册和登录两个数据库操作函数。2.1 用户注册功能int write_register(char* name, char* pass) { sqlite3* db NULL; int ret sqlite3_open(123.db, db); if (ret ! SQLITE_OK) { fprintf(stderr, sqlite3_open %s\n, sqlite3_errmsg(db)); sqlite3_close(db); return 0; } sqlite3_stmt* stmt; // 使用占位符?防止SQL注入 const char* sql INSERT INTO user (name, pass) VALUES (?, ?);; ret sqlite3_prepare_v2(db, sql, -1, stmt, NULL); if (ret ! SQLITE_OK) { fprintf(stderr, sqlite3_prepare_v2 INSERT failed: %s\n, sqlite3_errmsg(db)); sqlite3_close(db); return 0; } // 绑定参数到占位符 sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, pass, -1, SQLITE_STATIC); ret sqlite3_step(stmt); if (ret ! SQLITE_DONE) { fprintf(stderr, sqlite3_step INSERT failed: %s\n, sqlite3_errmsg(db)); sqlite3_finalize(stmt); sqlite3_close(db); return 0; } printf(Register success for user: %s\n, name); sqlite3_finalize(stmt); sqlite3_close(db); return 1; }2.2 用户登录验证int is_denglu_right(char* name, char* pass) { sqlite3* db NULL; int ret sqlite3_open(123.db, db); if (ret ! SQLITE_OK) { fprintf(stderr, sqlite3_open %s\n, sqlite3_errmsg(db)); sqlite3_close(db); return 0; } int flag 0; sqlite3_stmt* stmt; const char* sql SELECT * FROM user WHERE name ? AND pass ?;; ret sqlite3_prepare_v2(db, sql, -1, stmt, NULL); if (ret ! SQLITE_OK) { fprintf(stderr, sqlite3_prepare_v2 SELECT failed: %s\n, sqlite3_errmsg(db)); sqlite3_close(db); return 0; } sqlite3_bind_text(stmt, 1, name, -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, pass, -1, SQLITE_STATIC); ret sqlite3_step(stmt); if (ret SQLITE_ROW) { // 查询到数据则登录成功 flag 1; } sqlite3_finalize(stmt); sqlite3_close(db); return flag; }3. URL 解码功能Web 请求中 URL 参数会被编码如空格转为 、特殊字符转为 % XX需解码后才能正确处理void url_decode(char* dest, const char* src) { char c; while (*src) { if (*src %) { src; if (*src *(src1)) { // 解析十六进制编码 c ( ( (*src A) ? (toupper(*src) - A 10) : (*src - 0) ) 4 ) ( (*(src1) A) ? (toupper(*(src1)) - A 10) : (*(src1) - 0) ); *dest c; src 2; } } else if (*src ) { *dest ; // 号还原为空格 src; } else { *dest *src; } } *dest \0; }4. 商品搜索功能解析 /search 请求中的关键词解码后查询商品表动态生成搜索结果 HTMLelse if (strncmp(url, /search?, 8) 0) { char* name_ptr strstr(url, username); if (name_ptr) { char encoded_name[128] {0}; char decoded_name[128] {0}; sscanf(name_ptr, username%s, encoded_name); url_decode(decoded_name, encoded_name); // 解码搜索关键词 FILE* fp fopen(05.html, w); if (NULL fp) { perror(fopen 05.html); close(conn); continue; } // 生成搜索结果HTML头部 fprintf(fp, !DOCTYPE html\nhtml\nhead\nmeta charsetutf-8\ntitleSearch Results/title\n/head\nbody\n); fprintf(fp, h1Search results for: %s/h1\n, decoded_name); sqlite3* db NULL; if (sqlite3_open(123.db, db) SQLITE_OK) { char* errmsg NULL; char sql_cmd[512] {0}; // 模糊查询商品名称 sprintf(sql_cmd, select goods_id,goods_name,goods_img from goods where goods_name like %s%%;, decoded_name); ret sqlite3_exec(db, sql_cmd, detail3, fp, errmsg); if (ret ! SQLITE_OK) { fprintf(stderr, exec search [%s] msg:%s\n, sql_cmd, errmsg); sqlite3_free(errmsg); } sqlite3_close(db); } fprintf(fp, /body\n/html); fclose(fp); send_file(conn, ./05.html, FILE_HTML); } else { send_file(conn, ./03.html, FILE_HTML); } }5. HTTP 响应封装封装了文件大小计算、响应头发送、文件发送函数支持 HTML/PNG/JPG/ICO 等类型文件// 计算文件大小 long file_size(char* file) { int fd open(file, O_RDONLY); if (-1 fd) { perror(file size open error); fprintf(stderr, filename is %s\n, file); return -1; } long size lseek(fd, 0, SEEK_END); close(fd); return size; } // 发送HTTP响应头 int send_head(int conn, char* file, FILE_TYPE type) { char buf[256] {0}; long size file_size(file); if (size 0) return -1; char* http_cmd[7] {NULL}; http_cmd[0] HTTP/1.1 200 OK\r\n; http_cmd[1] Date: Tue, 15 Nov 1994 08:12:31 GMT\r\n; switch (type) { case FILE_HTML: http_cmd[2] Content-Type: text/html;charsetutf-8\r\n; break; case FILE_PNG: http_cmd[2] Content-Type: image/png\r\n; break; case FILE_JPG: http_cmd[2] Content-Type: image/jpeg\r\n; break; case FILE_ICO: http_cmd[2] Content-Type: image/x-icon\r\n; break; default: http_cmd[2] Content-Type: text/html;charsetutf-8\r\n; } http_cmd[3] buf; sprintf(buf, Content-Length: %ld\r\n, size); http_cmd[4] Connection: close\r\n; http_cmd[5] Server: MYWEBSer\r\n; http_cmd[6] Content-Language: zh-CN\r\n\r\n; for (int i 0; i 7; i) { send(conn, http_cmd[i], strlen(http_cmd[i]), 0); } return 0; } // 发送文件内容 int send_file(int conn, char* filename, FILE_TYPE type) { if (send_head(conn, filename, type) ! 0) { dprintf(conn, HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n); return 1; } int fd open(filename, O_RDONLY); if (-1 fd) { perror(open file to send); return 1; } char buf[4096] {0}; int rd_ret; while ((rd_ret read(fd, buf, sizeof(buf))) 0) { send(conn, buf, rd_ret, 0); } close(fd); return 0; }三、服务器主流程int main(int argc, char** argv) { int listfd socket(AF_INET, SOCK_STREAM, 0); if (-1 listfd) { perror(socket); return 1; } // 端口复用 int opt 1; setsockopt(listfd, SOL_SOCKET, SO_REUSEADDR, opt, sizeof(opt)); struct sockaddr_in ser, cli; bzero(ser, sizeof(ser)); ser.sin_family AF_INET; ser.sin_port htons(80); ser.sin_addr.s_addr INADDR_ANY; if (bind(listfd, (SA)ser, sizeof(ser)) -1) { perror(bind); return 1; } if (listen(listfd, 128) -1) { perror(listen); return 1; } printf(Server is running on port 80...\n); socklen_t len sizeof(cli); while (1) { int conn accept(listfd, (SA)cli, len); if (-1 conn) { if (errno EINTR) continue; perror(accept); continue; } char buf[1024] {0}; int ret recv(conn, buf, sizeof(buf) - 1, 0); if (ret 0) { close(conn); continue; } char method[16], url[512], ver[16]; sscanf(buf, %s %s %s, method, url, ver); // 路由分发 if (strcmp(method, GET) ! 0) { dprintf(conn, HTTP/1.1 501 Not Implemented\r\nConnection: close\r\n\r\n); } else if (strcmp(url, /) 0) { send_file(conn, ./03.html, FILE_HTML); } else if (strncmp(url, /register?, 10) 0) { // 注册逻辑 } else if (strncmp(url, /login?, 7) 0) { // 登录逻辑 } else if (strncmp(url, /search?, 8) 0) { // 搜索逻辑 } else if (strncmp(url, /detail_, 8) 0) { // 详情逻辑 } else if (strstr(url, .html)) { send_file(conn, url 1, FILE_HTML); } else { dprintf(conn, HTTP/1.1 404 Not Found\r\nConnection: close\r\n\r\n); } close(conn); } close(listfd); return 0; }四、编译与运行1. 编译命令需链接 SQLite3 库编译命令如下gcc 04ser.c -o web_shop -lsqlite3 -Wall2. 运行前准备创建 SQLite3 数据库文件 123.db并初始化表结构-- 用户表 CREATE TABLE user ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE NOT NULL, pass TEXT NOT NULL ); -- 商品表 CREATE TABLE goods ( goods_id INTEGER PRIMARY KEY, goods_name TEXT NOT NULL, goods_img TEXT, goods_desc TEXT );准备前端 HTML 文件03.html/04.html/06.html/07.html及商品图片资源。3. 启动服务器./web_shop浏览器访问 http://127.0.0.1 即可进入商城首页。五、核心优化点防 SQL 注入全程使用 SQLite3 预处理语句sqlite3_prepare_v2 绑定参数避免拼接 SQL 字符串。URL 解码处理前端传递的编码参数保证中文 / 特殊字符正常显示。资源类型适配支持 HTML、PNG、JPG、ICO 等多种文件类型的 HTTP 响应。错误处理完善的文件操作、数据库操作错误处理提升稳定性。端口复用设置SO_REUSEADDR选项避免服务器重启时端口占用问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询