c语言快递小项目

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);
}
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值