struct pack_head{
int fd;//通信的文件描述符
unsigned char type; //消息类型
unsigned char usertype; //用户类型:1:用户 2:快递员
char name[32]; //用户名
char paaswd[32]; //密码
char buf[32]; //调试信息
struct order_msg msg; //单号信息
};struct order_msg
{
int status; //0:表示未完成订单 1:表示已完成订单
long order; //订单号,由服务器端生成
char sender[32]; //发送人
char send_addr[64]; //发送地址
long send_tel; //发送电话
char reciver[32]; //收件人
char recive_addr[64]; //收件地址
long recive_tel; //收件人电话
float weight; //货物重量
char goods[32]; //货物名称
float price; //快递费用
};
服务器代码:
#include "1.h"
fd_set reads, temp;
int flag = 0;
pack msg;
sqlite3 *db;
void show1(); // 登录前
void show2(); // 登录后
void zhuce(pack *msg); // 注册
void denglu(pack *msg); // 登录
void zhuxiao(pack *msg); // 注销
void chakuaidi(pack *msg); // 查快递
void jikuaidi(pack *msg); // 寄快递
void quxiaodingdan(pack *msg); // 取消订单
void xiugaiyonghumima(pack *msg); // 修改用户信息
void xiugaikuaidixinxi(pack *msg); // 修改快递信息int main(int argc, char const *argv[])
{
char buf[256];if (argc != 2)
{
printf("用法 <port>\n");
return -1;
}
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket err");
return -1;
}
int flags = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); // 设置地址重用
struct sockaddr_in saddr, caddr;
saddr.sin_family = AF_INET;
saddr.sin_port = htons(atoi(argv[1]));
saddr.sin_addr.s_addr = INADDR_ANY;
;
socklen_t addrlen = sizeof(saddr);
if (bind(sockfd, (struct sockaddr *)&saddr, addrlen) < 0)
{
perror("bind err");
return -1;
}
if (listen(sockfd, 7) < 0)
{
perror("listen err");
return -1;
}
// 创建或打开数据库
if (sqlite3_open("./msg.db", &db) != 0)
{
printf("打开或创建数据库失败:%s", sqlite3_errmsg(db));
return -1;
}
char *errmsg = NULL;
// 创建三个表,分别是用户表,快递信息表,历史记录表
if (sqlite3_exec(db, "create table user(name char,password char);", NULL, NULL, &errmsg))
{
printf("创建用户表失败:%s\n", errmsg);
}
// status订单情况 order订单号 sender发送人 send_addr发送地址 send_tel发送电话 reciver收件人 recive_addr收件地址 recive_tel收件人电话 weight货物重量 goods货物名称 price快递费用
if (sqlite3_exec(db, "create table kuaidixinxi(status int,order_n long,sender char,send_addr char,send_tel long,reciver char,recive_addr char,recive_tel long,weight float,good char,price float );", NULL, NULL, &errmsg))
{
printf("创建快递信息表失败:%s\n", errmsg);
}
// status订单情况 order订单号 stime添加时间 rtime修改时间
if (sqlite3_exec(db, "create table lishijilu(status int,order_n long,stime char ,rtime char);", NULL, NULL, &errmsg))
{
printf("创建历史记录表失败:%s\n", errmsg);
}
FD_ZERO(&reads); //
FD_ZERO(&temp);
FD_SET(sockfd, &reads); // 将 sockfd 文件描述符添加到 readfds 集合中
int max = sockfd;
while (1)
{
temp = reads; // 将 read 文件描述符集合复制到 temp 中,以便 select 函数修改 temp 而不影响 read
int ret = select(max + 1, &temp, NULL, NULL, NULL); // 调用 select 监视文件描述符集合
if (ret < 0)
{
perror("select err");
return -1;
}
if (FD_ISSET(sockfd, &temp)) // 检查是否有新连接到达
{
int acceptfd = accept(sockfd, (struct sockaddr *)&caddr, &addrlen); // 接受新连接
if (acceptfd < 0)
{
perror("accept 失败");
return -1;
}
printf("accept成功\n");
printf("ip:%s port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
msg.fd = acceptfd; // 将新连接的文件描述符添加到 read 文件描述符集合中
FD_SET(acceptfd, &reads);
if (max < acceptfd) // 更新最大文件描述符值
{
max = acceptfd;
}
}
for (int i = sockfd + 1; i <= max; i++) // 遍历所有可能的文件描述符,检查是否有数据到达
{
if (FD_ISSET(i, &temp))
{
int rev = recv(i, &msg, sizeof(msg), 0);
msg.fd = i;
if (rev < 0)
{
perror("recv失败");
return -1;
}
else if (rev == 0) // 如果 recv 返回 0,表示客户端关闭连接
{
printf("%s退出\n", inet_ntoa(caddr.sin_addr));
FD_CLR(i, &reads); // 从 read 文件描述符集合中移除该文件描述符
close(i);
while (!FD_ISSET(max, &reads)) // 更新最大文件描述符值
{
max--;
}
}
else
{
printf("%s:%c\n", msg.name, msg.type);
if (!flag)
show1(); // 登录前
else
show2(); // 登陆后
printf("请输入:");
scanf("%c", &msg.type); // 消息类型
getchar();
printf("msg.type:%c\n", msg.type);
switch (msg.type)
{
case 'R':
zhuce(&msg); // 注册
break;
case 'L':
denglu(&msg); // 登录
break;
case 'D':
zhuxiao(&msg); // 注销
break;
case 'F':
chakuaidi(&msg); // 查快递
break;
case 'S':
jikuaidi(&msg); // 寄快递
break;
case 'C':
quxiaodingdan(&msg); // 取消订单
break;
case 'U':
xiugaiyonghumima(&msg); // 修改用户信息
break;
case 'P':
xiugaikuaidixinxi(&msg); // 修改快递信息
break;
case 'Q':
flag = 0; // 返回一级菜单
default:
break;
}
}
}
}
}
return 0;
}
void show1() // 登录前
{
printf("**R:注册**\n");
printf("**L:登录**\n");
printf("**D:注销**\n");
}
void show2() // 登录后
{
printf("**F:查快递**\n");
printf("**S:寄快递**\n");
printf("**C:取消订单**\n");
printf("**U:修改用户信息**\n");
printf("**P:修改快递信息**\n");
printf("**Q:返回一级菜单**\n");
}
void zhuce(pack *msg) // 注册
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf 的内容
char *errmsg = NULL; // 错误信息指针
char sql[128]; // 存储查询语句
char check_sql[128]; // 存储检查用户名是否存在的 SQL 查询语句
char **result = NULL; // 存储查询结果
int rows, columns; // 查询结果的行数和列数
while (1)
{
sprintf(check_sql, "select * from user where name='%s';", msg->name); // 构造检查用户名是否已存在的查询语句
if (sqlite3_get_table(db, check_sql, &result, &rows, &columns, &errmsg) != 0) // 执行查询
{
sprintf(msg->buf, "查询失败: %s", errmsg); // 查询失败,设置错误信息并退出循环
break;
}
if (rows > 0) // 如果查询结果中有行数据,说明用户名已存在
{
sprintf(msg->buf, "用户名已存在");
break;
}
sprintf(sql, "insert into user values('%s','%s');", msg->name, msg->paaswd); // 插入用户信息的语句
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0) // 执行插入操作
{
sprintf(msg->buf, "err %s", errmsg);
printf("失败\n");
break;
}
else
{
printf("%s\n", sql);
sprintf(msg->buf, "okk!!!");
printf("成功\n");
break;
}
}
send(msg->fd, msg->buf, sizeof(msg->buf), 0); // 发送注册结果信息到客户端
}void denglu(pack *msg) // 登录
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf 的内容
char sql[128]; // 存储查询语句
char *errmsg = NULL; // 错误信息指针
char **result = NULL; // 存储查询结果
int rows, columns; // 查询结果的行数和列数
while (1)
{
sprintf(sql, "select * from user where name = '%s' and password = '%s';", msg->name, msg->paaswd); // 构造登录验证查询语句
int sqlget = sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg); // 查询
if (sqlget != 0) // 查询失败,设置错误信息并退出循环
{
sprintf(msg->buf, "sqlite3_get_table 错误: %s", errmsg);
break;
}
else if (rows > 0) // 查询结果中有数据,登录成功
{
sprintf(msg->buf, "okk");
printf("成功\n");
break;
}
else
{
sprintf(msg->buf, "name or paaswd worng!!");
printf("失败");
break;
}
}
send(msg->fd, msg->buf, strlen(msg->buf), 0); // 发送登录结果信息到客户端
}void zhuxiao(pack *msg) // 注销
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf 的内容
char sql[128]; // 存储查询语句
char *errmsg = NULL; // 错误信息指针
char **result = NULL; // 存储查询结果
int rows, columns; // 查询结果的行数和列数
while (1)
{
sprintf(sql, "delete from user where name = '%s';", msg->name); // 构造删除用户信息的语句
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0) // 执行删除操作
{
sprintf(msg->buf, "注销失败: %s", errmsg);
break;
}
else
{
printf("%s\n", sql);
sprintf(msg->buf, "注销成功");
break;
}
}
send(msg->fd, msg->buf, sizeof(msg->buf), 0); // 发送注销结果信息到客户端
}
void chakuaidi(pack *msg) // 查快递
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空消息缓冲区
memset(msg->msgg.sender, 0, sizeof(msg->msgg.sender)); // 清空发送人信息
memset(msg->msgg.send_addr, 0, sizeof(msg->msgg.send_addr)); // 清空发送地址
memset(msg->msgg.reciver, 0, sizeof(msg->msgg.reciver)); // 清空收件人信息
memset(msg->msgg.recive_addr, 0, sizeof(msg->msgg.recive_addr)); // 清空收件地址
memset(msg->msgg.goods, 0, sizeof(msg->msgg.goods)); // 清空货物名称
char sql[1024];
char *errmsg = NULL;
char **result = NULL;
int rows, columns;
sprintf(sql, "select * from kuaidixinxi where send_tel = %ld;", msg->msgg.send_tel); // 创建查询语句
int rc = sqlite3_get_table(db, sql, &result, &rows, &columns, &errmsg); // 执行查询
if (rc != 0) // 查询失败,输出错误信息
{
sprintf(msg->buf, "查询失败: %s", errmsg);
}
else
{
if (rows > 0) // 查询到信息,格式化输出
{
for (int i = 1; i <= rows; ++i)
{
strcat(msg->buf, "查询到的信息:");
for (int j = 0; j < columns; ++j)
{
strcat(msg->buf, result[i * columns + j]);
strcat(msg->buf, " ");
}
strcat(msg->buf, "\n");
}
}
else// 没有找到快递信息
{
strcpy(msg->buf, "没有找到该快递信息");
}
}
send(msg->fd, msg->buf, strlen(msg->buf) - 1, 0); // 发送结果到客户端
}void jikuaidi(pack *msg) // 寄快递
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空缓冲区
msg->msgg.status = 0; // 设置状态为0(寄出)
msg->msgg.price = msg->msgg.weight * 5; // 计算价格(重量乘以单位价格)
char sql[1024]; // 用于存储插入快递信息的语句
char sql1[1024]; // 用于存储插入历史记录的语句
char *errmsg = NULL; // 错误信息
char **result = NULL; // 查询结果
int rows, columns; // 查询结果的行数和列数
time_t t; // 当前时间
struct tm *tm; // 时间结构体
char stime[100]; // 格式化时间字符串
time(&t); // 获取当前时间
tm = localtime(&t); // 转换为本地时间
msg->msgg.order = t; // 记录订单时间
while (1)
{
sprintf(stime, "%d-%d-%d-%d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour);// 格式化时间字符串
snprintf(sql, sizeof(sql), "insert into kuaidixinxi values (%d,%ld,'%s','%s',%ld,'%s','%s',%ld,%f,'%s',%f);",
msg->msgg.status, msg->msgg.order, msg->msgg.sender, msg->msgg.send_addr, msg->msgg.send_tel,
msg->msgg.reciver, msg->msgg.recive_addr, msg->msgg.recive_tel, msg->msgg.weight, msg->msgg.goods, msg->msgg.price);// 构造插入快递信息的 SQL 语句
snprintf(sql1, sizeof(sql1), "insert into lishijilu values (%d,%ld,'%s',0);",
msg->msgg.status, msg->msgg.order, stime);// 构造插入历史记录的 SQL 语句
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0) // 执行插入快递信息的操作
{
sprintf(msg->buf, "寄快递失败: %s", errmsg);
break;
}
else
{
printf("%s\n", sql); // 打印 SQL 语句
}
if (sqlite3_exec(db, sql1, NULL, NULL, &errmsg) != 0)// 执行插入历史记录的操作
{
sprintf(msg->buf, "放入历史记录失败: %s", errmsg);
break;
}
else
{
printf("%s\n", sql1); // 打印语句
sprintf(msg->buf, "寄快递成功");
break;
}
}
send(msg->fd, msg->buf, sizeof(msg->buf), 0);// 发送结果到客户端
}
void quxiaodingdan(pack *msg) // 取消订单
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空缓冲区
char sql[1024]; // 用于存储删除快递信息的语句
char sql1[1024]; // 用于存储更新历史记录的语句
char *errmsg = NULL; // 错误信息
char **result = NULL; // 查询结果
int rows, columns; // 查询结果的行数和列数
time_t t; // 当前时间
struct tm *tm; // 时间结构体
char rtime[100]; // 格式化时间字符串
time(&t); // 获取当前时间
tm = localtime(&t); // 转换为本地时间
while (1)
{
sprintf(rtime, "%d-%d-%d-%d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour);// 格式化时间字符串
snprintf(sql, sizeof(sql), "delete from kuaidixinxi where order_n=%ld;", msg->msgg.order);// 创建删除快递信息的 SQL 语句
snprintf(sql1, sizeof(sql1), "update lishijilu set rtime='%s' where order_n=%ld;", rtime, msg->msgg.order);// 创建更新历史记录的 SQL 语句
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)// 执行删除操作
{
sprintf(msg->buf, "取消订单失败: %s", errmsg);
break;
}
else
{
printf("%s\n", sql); // 打印语句
}
if (sqlite3_exec(db, sql1, NULL, NULL, &errmsg) != 0) // 执行更新历史记录操作
{
sprintf(msg->buf, "放入历史记录失败: %s", errmsg);
break;
}
else
{
printf("%s\n", sql1); // 打印语句
sprintf(msg->buf, "取消订单成功");
break;
}
}
send(msg->fd, msg->buf, sizeof(msg->buf), 0);// 发送结果到客户端
}
void xiugaiyonghumima(pack *msg) // 修改用户密码
{
memset(msg->buf, 0, sizeof(msg->buf)); // 清空消息缓冲区
char sql[128]; // 用于存储更新用户密码的语句
char *errmsg = NULL; // 错误信息
char **result = NULL; // 查询结果(未使用)
int rows, columns; // 查询结果的行数和列数(未使用)
while (1)
{
// 生成更新用户密码的 SQL 语句
sprintf(sql, "update user set password='%s' where name = '%s';", msg->paaswd, msg->name);
// 执行 SQL 查询
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
{
// 如果执行失败,返回错误信息
sprintf(msg->buf, "修改失败: %s", errmsg);
break;
}
else
{
// 打印 SQL 语句(调试用)
printf("%s\n", sql);
// 设置成功信息
sprintf(msg->buf, "修改密码成功");
break;
}
}
// 发送结果消息
send(msg->fd, msg->buf, sizeof(msg->buf), 0);
}
void xiugaikuaidixinxi(pack *msg) // 修改快递信息
{
char sql[1024]; // SQL 查询语句
char *errmsg = NULL; // 错误信息
printf("%s\n", msg->msgg.sender); // 打印发送人信息(调试用)
while (1)
{
// 根据 buf 的内容生成相应的 SQL 更新语句
if (strcmp(msg->buf, "发送人") == 0)
{
sprintf(sql, "update kuaidixinxi set sender='%s' where order_n=%ld;", msg->msgg.sender, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "发送地址") == 0)
{
sprintf(sql, "update kuaidixinxi set send_addr='%s' where order_n=%ld;", msg->msgg.send_addr, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "发送人电话") == 0)
{
sprintf(sql, "update kuaidixinxi set send_tel=%ld where order_n=%ld;", msg->msgg.send_tel, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "收件人") == 0)
{
sprintf(sql, "update kuaidixinxi set reciver='%s' where order_n=%ld;", msg->msgg.reciver, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "收件地址") == 0)
{
sprintf(sql, "update kuaidixinxi set recive_addr='%s' where order_n=%ld;", msg->msgg.recive_addr, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "收件人电话") == 0)
{
sprintf(sql, "update kuaidixinxi set recive_tel=%ld where order_n=%ld;", msg->msgg.recive_tel, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "货物重量") == 0)
{
sprintf(sql, "update kuaidixinxi set weight=%f where order_n=%ld;", msg->msgg.weight, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
else if (strcmp(msg->buf, "货物名称") == 0)
{
sprintf(sql, "update kuaidixinxi set good='%s' where order_n=%ld;", msg->msgg.goods, msg->msgg.order);
memset(msg->buf, 0, sizeof(msg->buf)); // 清空 buf
}
// 计算快递价格
msg->msgg.price = msg->msgg.weight * 5;
// 执行 SQL 查询
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
{
// 如果执行失败,返回错误信息
sprintf(msg->buf, "修改快递信息失败: %s", errmsg);
break;
}
else
{
// 打印 SQL 语句(调试用)
printf("%s\n", sql);
// 设置成功信息
sprintf(msg->buf, "修改快递信息成功");
break;
}
}
// 发送结果消息
send(msg->fd, msg->buf, sizeof(msg->buf), 0);
}
标签:语言,项目,char,快递,msgg,sql,msg,NULL,buf From: https://blog.csdn.net/weixin_63207763/article/details/142265560