首页 > 编程语言 >网络编程练习:华清速递

网络编程练习:华清速递

时间:2024-09-23 20:21:06浏览次数:9  
标签:void 编程 华清 速递 sql printf msg sizeof PACK

【1】服务器代码

#include "head.h"

fd_set rdfs;
int num = 1;
sqlite3 *db;
sqlite3 *mdb;

int init_server(int port); // 初始化服务器
void Register(PACK *msg);  // 注册
// void *handler(void *arg);  // 线程函数
void Login(PACK *msg);    // 上线
void Send_out(PACK *msg); // 寄快递
void Search(PACK *msg);   // 客户端查快递
int callback(void *arg, int num, char **value, char **name);
void Change_express(PACK *msg); // 更改快递信息
void Cancel_express(PACK *msg); // 取消快递
void Change_user(PACK *msg);    // 修改用户信息
void Delete_user(PACK *msg);    // 注销
void Send_express(PACK *msg);   // 快递员送快递
void Search_status(PACK *msg);  // 快递员按状态查快递
void Histroy(PACK *msg);        // 查历史记录

char *errmsg = NULL;
char sql[1024];

int main(int argc, char const *argv[])
{
    pthread_t tid;
    // 创建表
    fd_set tempfs;
    // 可以连接多个客户端(监听键盘0和sockfd)
    int maxfd, acceptfd;
    int ret, rev;
    char buf[256] = {0};
    PACK msg;
    // 如果不传递端口,那么使用默认端口8888
    int port = 8888;

    if (argc > 1)
    {
        port = atoi(argv[1]);
    }

    // 初始化服务器
    int sockfd = init_server(port);
    printf("init ok\n");

    // 打开数据库
    if (sqlite3_open("./user.db", &db) != SQLITE_OK)
    {
        fprintf(stderr, "open err:%s", sqlite3_errmsg(db));
        return -1;
    }
    if (sqlite3_open("./msg.db", &mdb) != SQLITE_OK)
    {
        fprintf(stderr, "open err:%s", sqlite3_errmsg(mdb));
        return -1;
    }
    printf("open ok\n");
    // 操作
    // char *errmsg = NULL;
    // 创建表
    if (sqlite3_exec(db, "create table user(name char primary key,password char);", NULL, NULL, &errmsg))
    {
        fprintf(stderr, "creat user err:%s\n", errmsg);
        // return -1;
    }
    //
    if (sqlite3_exec(mdb, "create table info(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))
    {
        fprintf(stderr, "creat info err:%s\n", errmsg);
        // return -1;
    }

    if (sqlite3_exec(mdb, "create table his(status int,order_n long,stime char ,rtime char);",
                     NULL, NULL, &errmsg))
    {
        fprintf(stderr, "creat his err:%s\n", errmsg);
        // return -1;
    }

    // 清空表
    FD_ZERO(&rdfs);
    FD_ZERO(&tempfs);
    // 将文件描述符添加到表中
    FD_SET(sockfd, &rdfs);
    maxfd = sockfd;
    while (1)
    {
        tempfs = rdfs;
        ret = select(maxfd + 1, &tempfs, NULL, NULL, NULL);
        if (ret < 0)
        {
            perror("select err");
            return -1;
        }
        if (FD_ISSET(sockfd, &tempfs))
        {
            acceptfd = accept(sockfd, NULL, NULL);
            if (acceptfd < 0)
            {
                perror("accept err");
                return -1;
            }
            printf("accept ok\n");
            // printf("ip:%s port:%d\n", inet_ntoa(caddr.sin_addr), ntohs(caddr.sin_port));
            /*心跳包*/
            msg.acceptfd = acceptfd;
            FD_SET(acceptfd, &rdfs);
            if (maxfd < acceptfd)
                maxfd = acceptfd;
            // pthread_create(&tid, NULL, handler, &msg);
            // pthread_detach(tid);
        }
        for (int i = sockfd + 1; i <= maxfd; i++)
        {
            if (FD_ISSET(i, &tempfs))
            {
                // 处理客户端请求
                rev = recv(i, &msg, sizeof(msg), 0);
                msg.acceptfd = i;
                if (rev < 0)
                {
                    perror("recv err");
                    /*心跳包错误检测*/
                    return -1;
                }
                else if (rev == 0)
                {
                    printf("client exit\n");
                    close(i);
                    FD_CLR(i, &rdfs);
                    // if (i == maxfd)
                    //     maxfd--;
                    while (!FD_ISSET(maxfd, &rdfs))
                        maxfd--;
                }
                else
                {
                    printf("%s:%c\n", msg.name, msg.type);
                    switch (msg.type)
                    {
                    case 'R':
                        Register(&msg);
                        break;
                    case 'L':
                        Login(&msg);
                        break;
                    case 'S':
                        Send_out(&msg);
                        break;
                    case 'F':
                        Search(&msg);
                        break;
                    case 'P':
                        Change_express(&msg);
                        break;
                    case 'C':
                        Cancel_express(&msg);
                        break;
                    case 'U':
                        Change_user(&msg);
                        break;
                    case 'D':
                        Delete_user(&msg);
                        break;
                    case 'E':
                        Send_express(&msg);
                        break;
                    case 'A':
                        Search_status(&msg);
                        break;
                    case 'H':
                        Histroy(&msg);
                        break;

                    default:
                        break;
                    }
                }
            }
        }
    }

    return 0;
}

int init_server(int port) // 创建监听套接字
{

    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        perror("socket failed");
        exit(2);
    }

    // 设置地址重用
    int opt = 1;
    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));

    struct sockaddr_in local;
    local.sin_family = AF_INET;
    local.sin_port = htons(port);
    local.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock, (struct sockaddr *)&local, sizeof(local)) < 0)
    {
        perror("bind failed");
        exit(3);
    }

    if (listen(sock, 5) < 0)
    {
        perror("listen failed");
        exit(4);
    }

    return sock;
}
/**
 * @brief 服务器处理注册
 * 得到用户输入用户名和密码并拼接sql语句
 * 执行sql语句
 * 封装执行结果并回发客户端
 */
void Register(PACK *msg)
{
    sprintf(sql, "insert into user values('%s','%s');", msg->name, msg->paaswd);
    printf("%s\n", sql);
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg))
    {
        fprintf(stderr, "insert err:%s\n", errmsg);
        return;
    }
    strcpy(msg->buf, "注册成功");
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    return;
}

/**
 * @brief 服务器处理登录
 * 得到用户输入用户名和密码并拼接sql语句
 * 执行sql语句
 * 判断输入的用户名以及密码是否正确
 * 封装执行结果并回发客户端
 */
void Login(PACK *msg)
{
    sprintf(sql, "select * from user where name = '%s' and password = '%s';", msg->name, msg->paaswd);
    printf("%s\n", sql);
    char **result = NULL;
    int row = 0, column = 0;
    sqlite3_get_table(db, sql, &result, &row, &column, &errmsg);
    printf("%d\n", row);
    if (row == 0)
        strcpy(msg->buf, "用户名或密码错误");
    else
        strcpy(msg->buf, "登录成功");
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    sqlite3_free_table(result);
    return;
}
/**
 * @brief 服务器寄快递
 * 得到用户输入快递信息,
 * 根据货物重量计算快递价钱,系统给出随机快递单号
 * 将快递信息拼接sql语句
 * 执行sql语句
 * 并将快递信息添加到历史记录表中
 * 返回执行信息给客户端
 */
void Send_out(PACK *msg)
{
    time_t t;
    struct tm *tm;
    time(&t);
    tm = localtime(&t);
    srand((unsigned int)time(NULL)); // 获取随机数种子
    msg->msgg.order = rand();        // 生成随机数
    char ttime[1024];
    sprintf(ttime, "%d-%d-%d %d", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour);
    sprintf(sql, "insert into his values (%d,%ld,'%s',0);",
            msg->msgg.status, msg->msgg.order, ttime);
    printf("%s\n", sql);
    if (sqlite3_exec(mdb, sql, NULL, NULL, &errmsg))
    {
        fprintf(stderr, "insert err:%s\n", errmsg);
        return;
    }
    memset(sql, 0, sizeof(sql));
    msg->msgg.price = msg->msgg.weight * 12; // 快递价钱
    msg->msgg.status = 0;
    sprintf(sql, "insert into info 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);
    if (sqlite3_exec(mdb, sql, NULL, NULL, &errmsg))
    {
        fprintf(stderr, "insqert err:%s\n", errmsg);
        return;
    }
    strcpy(msg->buf, "寄件成功");
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);
}
/**
 * @brief 服务器处理查询快递请求
 * 得到用户输入查询信息拼接sql语句
 * 执行sql语句
 * 回调函数将查询到的信息发送给客户端
 */
void Search(PACK *msg)
{
    sprintf(sql, "select * from info where send_tel = %ld;", msg->msgg.send_tel);
    if (sqlite3_exec(mdb, sql, callback, "hello", &errmsg) != 0)
    {
        fprintf(stderr, "select err:%s\n", errmsg);
        return;
    }
    printf("select okk\n");
    // 专门用于查询数据的函数:sqlite3_get_table
    // row:行
    // column:列
    char **result = NULL;
    int row = 0, column = 0;
    if (sqlite3_get_table(mdb, sql, &result, &row, &column, &errmsg) != 0)
    {
        perror("查询失败\n");
        return;
    }
    memset(sql, 0, sizeof(sql));
    // strcpy(msg->buf, "查询成功");
    // send(msg->acceptfd, msg, sizeof(PACK), 0);
    int k = 11;
    printf("row:%d column:%d\n", row, column);

    if (row != 0)
    {
        for (int i = 1; i <= row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                strcat(sql, result[k++]);
                sql[strlen(sql)] = ' ';
            }
            sql[strlen(sql)] = '\n';
        }
        send(msg->acceptfd, sql, sizeof(sql), 0);
        printf("查询成功\n");
    }
    else
    {
        strcpy(sql, "查询失败");
        send(msg->acceptfd, sql, sizeof(sql), 0);
    }

    return;
}
/**
 * @brief 回调函数
 */
int callback(void *arg, int num, char **value, char **name)
{
    // 每查询到一条符合条件的数据就会调用一次函数
    static int i = 1;
    printf("%s:%d\n", (char *)arg, i++);
    // num:列数
    // value:值
    // name:列名
    for (int j = 0; j < num; j++)
    {
        printf("%s ", name[j]);
    }
    putchar(10);
    for (int j = 0; j < num; j++)
    {
        printf("%s ", value[j]);
    }
    putchar(10);
    printf("***************************************\n");
    return 0; // 必须存在,不然sqlite_exec函数会报错
}
/**
 * @brief 服务器处理修改快递信息请求
 * 得到用户输入的要修改的快递信息并拼接sql语句
 * 执行sql语句
 * 执行结果发送给客户端
 */

void Change_express(PACK *msg)
{
    char sqlstr[1024];
    char *errmsg;
    sprintf(sqlstr, "update info set send_tel=%ld , send_addr =\"%s\" where order_n=%ld;",
            msg->msgg.send_tel, msg->msgg.send_addr, msg->msgg.order);
    if (sqlite3_exec(mdb, sqlstr, NULL, NULL, &errmsg))
    {
        fprintf(stderr, "update err:%s\n", errmsg);
        strcpy(msg->buf, "fail err!!!");
    }
    else
    {
        strcpy(msg->buf, "updata ok!!!");
    }
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);

    return;
}
/**
 * @brief 服务器处理取消快递信息请求
 * 得到用户输入的要取消的快递信息并拼接sql语句
 * 执行sql语句
 * 执行结果发送给客户端
 */
void Cancel_express(PACK *msg)
{
    sprintf(sql, "delete from info where order_n = %ld;", msg->msgg.order);
    if (sqlite3_exec(mdb, sql, NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "delete err:%s\n", errmsg);
        return;
    }
    else
    {
        strcpy(msg->buf, "删除成功");
    }
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    return;
}
/**
 * @brief 服务器处理修改用户信息请求
 * 得到用户输入的要修改的信息并拼接sql语句
 * 执行sql语句
 * 执行结果发送给客户端
 */
void Change_user(PACK *msg)
{
    sprintf(sql, "update user set password = '%s' where name = '%s';", msg->paaswd, msg->name);
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "update err:%s\n", errmsg);
        return;
    }
    else
    {
        strcpy(msg->buf, "修改成功");
    }
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    return;
}
/**
 * @brief 服务器处理要注销用户信息请求
 * 得到用户输入的要注销的用户信息并拼接sql语句
 * 执行sql语句查询输入信息是否正确
 * 执行sql语句从表里删除客户信息
 * 执行结果发送给客户端
 */
void Delete_user(PACK *msg)
{
    sprintf(sql, "delete from user where name = '%s';", msg->name);
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "delete err:%s\n", errmsg);
        return;
    }
    else
    {
        strcpy(msg->buf, "注销成功");
    }
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    return;
}
/**
 * @brief 服务器处理要送达请求
 * 得到用户输入的要送达快递的信息并拼接sql语句
 * 执行sql语句修改快递信息为送达
 * 执行sql语句将送达信息更新到历史记录表中
 * 执行结果发送给客户端
 */
void Send_express(PACK *msg)
{
    msg->msgg.status = 1;
    sprintf(sql, "update his set status = %d where order_n = %ld", msg->msgg.status, msg->msgg.order); // 更新历史记录表
    if (sqlite3_exec(mdb, sql, NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "update err:%s\n", errmsg);
        return;
    }
    sprintf(sql, "update info set status = %d where order_n = %ld", msg->msgg.status, msg->msgg.order);
    if (sqlite3_exec(mdb, sql, NULL, NULL, &errmsg) != 0)
    {
        fprintf(stderr, "update err:%s\n", errmsg);
        return;
    }
    else
    {
        strcpy(msg->buf, "快递已送达");
    }
    printf("%s\n", msg->buf);
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    return;
}
/**
 * @brief 服务器处理快递员根据快递是否送达状态查询快递信息请求
 * 得到用户输入的要查询的状态并拼接sql语句
 * 执行sql语句
 * 回调函数将查询到的信息发送给客户端
 */
void Search_status(PACK *msg)
{
    sprintf(sql, "select * from info where order_n = %ld;", msg->msgg.order);
    if (sqlite3_exec(mdb, sql, callback, "hello", &errmsg) != 0)
    {
        fprintf(stderr, "select err:%s\n", errmsg);
        return;
    }
    printf("select okk\n");
    // 专门用于查询数据的函数:sqlite3_get_table
    // row:行
    // column:列
    char **result = NULL;
    int row = 0, column = 0;
    if (sqlite3_get_table(mdb, sql, &result, &row, &column, &errmsg) != 0)
    {
        perror("查询失败\n");
        return;
    }
    memset(sql, 0, sizeof(sql));
    // strcpy(msg->buf, "查询成功");
    // send(msg->acceptfd, msg, sizeof(PACK), 0);
    int k = 11;
    printf("row:%d column:%d\n", row, column);
    strcpy(sql, result[k]);
    send(msg->acceptfd, sql, sizeof(sql), 0);
    printf("查询成功\n");
    return;
}
/**
 * @brief 服务器处理查询历史记录请求
 * 得到用户输入的要查询的选项查询信息并拼接sql语句
 * 执行sql语句
 * 回调函数将查询到的信息发送给客户端
 */

void Histroy(PACK *msg)
{
    char sql[1024];
    char *errmsg;
    if (!strncmp(msg->buf, "all", 1))
        sprintf(sql, "select * from his;");
    // sqlite3_exec(mdb, "select * from his;", callback, msg, &errmsg);
    else
        sprintf(sql, "select * from his where stime='%s';", msg->buf);
    printf("%s\n", sql);
    char **result = NULL;
    int row = 0, column = 0;
    if (sqlite3_get_table(mdb, sql, &result, &row, &column, &errmsg) != 0)
    {
        perror("查询失败\n");
        return;
    }
    memset(sql, 0, sizeof(sql));
    // strcpy(msg->buf, "查询成功");
    // send(msg->acceptfd, msg, sizeof(PACK), 0);
    int k = 4;
    printf("row:%d column:%d\n", row, column);

    if (row != 0)
    {
        for (int i = 1; i <= row; i++)
        {
            for (int j = 0; j < column; j++)
            {
                strcat(sql, result[k++]);
                sql[strlen(sql)] = ' ';
            }
            sql[strlen(sql)] = '\n';
        }
        send(msg->acceptfd, sql, sizeof(sql), 0);
        printf("查询成功\n");
    }
    else
    {
        strcpy(sql, "查询失败");
        send(msg->acceptfd, sql, sizeof(sql), 0);
    }
    return;
}

【2】 用户端代码

#include "head.h"

int flag = 0; // 标志位,区分一级界面和二级界面

void show();
void show2();
void Register(PACK *msg);
void Login(PACK *msg);
void Send_out(PACK *msg);
void Search(PACK *msg);
void Change_express(PACK *msg);
void Cancel_express(PACK *msg);
void Change_user(PACK *msg);
void Delete_user(PACK *msg);

int sockfd;

int main(int argc, char const *argv[])
{
    char info[128] = {0};
    char ip[128] = "192.168.253.150";
    int port = 8888;

    // 1.创建流式套接字

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("socket err");
        return -1;
    }
    printf("sockfd:%d\n", sockfd);

    // 2.打开配置文件,读取ip地址和端口号

    // 3.填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    saddr.sin_addr.s_addr = inet_addr(ip);

    // 4.请求连接
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err");
        return -1;
    }
    printf("connect ok\n");
    // 5.发送消息
    PACK msg;
    // msg.acceptfd = sockfd;
    while (1)
    {
        msg.acceptfd = sockfd;
        if (!flag)
            show(); // 登录前
        else
            show2(); // 登录后
        printf("请输入:");
        scanf("%c", &msg.type);
        getchar();
        printf("msg.type:%c\n", msg.type);
        switch (msg.type)
        {
        case 'R':
            Register(&msg); // 注册
            break;
        case 'L':
            Login(&msg); // 登录
            break;
        case 'S':
            Send_out(&msg); // 寄快递
            break;
        case 'F':
            Search(&msg); // 查快递
            break;
        case 'P':
            Change_express(&msg); // 修改快递信息
            break;
        case 'C':
            Cancel_express(&msg); // 取消订单
            break;
        case 'U':
            Change_user(&msg); // 修改用户信息
            break;
        case 'D':
            Delete_user(&msg); // 注销用户
            break;
        case 'Q':
            flag = 0; // 返回一级菜单
            break;
        default:
            break;
        }
    }
    // 6.关闭
    close(sockfd);

    return 0;
}

void show()
{
    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");
}

/**
 * @brief 客户端注册
 * 用户输入用户名和密码
 * 封装消息
 * 发送
 * 接收并输出结果
 */
void Register(PACK *msg)
{
    printf("请输入用户名:");
    scanf("%s", msg->name);
    getchar();
    // fgets(msg->name, sizeof(msg->name), stdin);
    // if (msg->name[strlen(msg->name) - 1] == '\n')
    //     msg->name[strlen(msg->name) - 1] = '\0';
    printf("请输入密码:");
    scanf("%s", msg->paaswd);
    getchar();
    // fgets(msg->paaswd, sizeof(msg->paaswd), stdin);
    // if (msg->paaswd[strlen(msg->paaswd) - 1] == '\n')
    //     msg->paaswd[strlen(msg->paaswd) - 1] = '\0';
    printf("name:%s  pass:%s\n", msg->name, msg->paaswd);
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

/**
 * @brief 客户端登录
 * 用户输入用户名和密码
 * 封装消息
 * 发送
 * 接收并输出结果
 *
 */
void Login(PACK *msg)
{
    while (1)
    {
        printf("请输入用户名:");
        // fgets(msg->name, sizeof(msg->name), stdin);
        // if (msg->name[strlen(msg->name) - 1] == '\n')
        //     msg->name[strlen(msg->name) - 1] = '\0';
        scanf("%s", msg->name);
        getchar();
        printf("请输入密码:");
        // fgets(msg->paaswd, sizeof(msg->paaswd), stdin);
        // if (msg->paaswd[strlen(msg->paaswd) - 1] == '\n')
        //     msg->paaswd[strlen(msg->paaswd) - 1] = '\0';
        scanf("%s", msg->paaswd);
        getchar();

        send(sockfd, msg, sizeof(PACK), 0);
        recv(sockfd, msg, sizeof(PACK), 0);

        if (strcmp(msg->buf, "登录成功") == 0)
        {
            printf("%s\n\n", msg->buf);
            flag = 1;
            break;
        }
        else
        {
            printf("%s\n\n", msg->buf);
        }
    }
    return;
}

/**
 * @brief 客户端寄快递
 * 输入发件人姓名,地址,电话;收件人姓名,地址,电话;货物重量,名称
 * 发送
 * 接收并输出结果
 */
void Send_out(PACK *msg)
{
    printf("请输入发件人姓名、地址、电话:");
    scanf("%s%s%ld", msg->msgg.sender, msg->msgg.send_addr, &(msg->msgg.send_tel));
    getchar();
    printf("请输入收件人姓名、地址、电话:");
    scanf("%s%s%ld", msg->msgg.reciver, msg->msgg.recive_addr, &(msg->msgg.recive_tel));
    getchar();
    printf("请输入货物重量、名称:");
    scanf("%f%s", &(msg->msgg.weight), msg->msgg.goods);
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
}

/**
 * @brief 客户端查询
 * 输入要查询订单的手机号
 * 发送
 * 接收并输出查询结果
 */
void Search(PACK *msg)
{
    char sql[1024] = {0};
    printf("请输入要查询订单的手机号:");
    scanf("%ld", &(msg->msgg.send_tel));
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    // printf("%s\n", msg->buf);
    recv(sockfd, sql, sizeof(sql), 0);
    if (strcmp(sql, "查询失败") != 0)
    {
        printf("订单状态    订单号  发件人姓名  地址    电话    收件人姓名  地址    电话    货物重量    名称\n");
        printf("%s\n\n", sql);
    }
    else
    {
        printf("%s\n", sql);
    }

    return;
}
/**
 * @brief 客户端修改快递信息
 * 输入要修改快递单号及快递信息的电话和地址
 * 发送
 * 接收并输出结果
 */
void Change_express(PACK *msg)
{
    printf("请输入要修改快递单号");
    scanf("%ld", &msg->msgg.order);
    getchar();
    printf("请输入要修改快递信息发件人的电话和地址");
    scanf("%ld %s", &msg->msgg.send_tel, msg->msgg.send_addr);
    getchar();
    send(msg->acceptfd, msg, sizeof(PACK), 0);
    recv(msg->acceptfd, msg, sizeof(PACK), 0);
    printf("%s\n", msg->buf);
    return;
}
/**
 * @brief 客户端取消寄件
 * 输入要取消快递单号
 * 发送
 * 接收并输出结果
 */
void Cancel_express(PACK *msg)
{
    printf("请输入要取消的订单号:");
    scanf("%ld", &(msg->msgg.order));
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

/**
 * @brief 客户端修改用户信息
 * 输入要修改的密码
 * 发送
 * 接收并输出结果
 */
void Change_user(PACK *msg)
{
    printf("请输入要修改的用户名:");
    scanf("%s", msg->name);
    getchar();
    printf("请输入要修改的密码:");
    scanf("%s", msg->paaswd);
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}
/**
 * @brief 客户端注销用户信息
 * 输入要注销的用户名、密码
 * 发送
 * 接收并输出结果
 */
void Delete_user(PACK *msg)
{
    printf("请输入要删除的用户名:");
    scanf("%s", msg->name);
    getchar();
    printf("请输入密码:");
    scanf("%s", msg->paaswd);
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

【3】快递员端代码

#include "head.h"

int flag = 0;

void show();
void show2();
void Register(PACK *msg);
void Login(PACK *msg);
void Search_status(PACK *msg);
void Change_user(PACK *msg);
void Delete_user(PACK *msg);
void Send_express(PACK *msg);
void Histroy(PACK *msg);

int sockfd;

int main(int argc, char const *argv[])
{
    char info[128] = {0};
    char ip[128] = "192.168.253.150";
    // char port[32] = {0};
    int port = 8888;

    // 1.创建流式套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
    {
        perror("sockfd err");
        return -1;
    }

    // 2.打开配置文件,读取ip地址和端口号

    // 3.填充结构体
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    saddr.sin_addr.s_addr = inet_addr(ip);

    // 4.请求连接
    if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
    {
        perror("connect err");
        return -1;
    }
    printf("connect ok\n");

    // 5.发送消息
    PACK msg;

    while (1)
    {
        msg.acceptfd = sockfd;
        if (!flag)
            show();
        else
            show2();
        printf("请输入:");
        scanf("%c", &msg.type);
        getchar();
        printf("msg.type:%c\n", msg.type);
        switch (msg.type)
        {
        case 'R':
            Register(&msg); // 注册
            break;
        case 'L':
            Login(&msg); // 登录
            break;
        case 'E':
            Send_express(&msg); // 送快递
            break;
        case 'A':
            Search_status(&msg); // 查快递
            break;
        case 'H':
            Histroy(&msg); // 查询历史记录
            break;
        case 'U':
            Change_user(&msg); // 修改用户信息
            break;
        case 'D':
            Delete_user(&msg); // 注销用户
            break;
        case 'Q':
            flag = 0; // 返回一级菜单
            break;
        default:
            break;
        }
    }
    // 6.关闭
    close(sockfd);
    return 0;
}

// 一级界面显示
void show()
{
    printf("**R:注册**\n");
    printf("**L:登录**\n");
    printf("**D:注销**\n");
}

// 二级界面显示
void show2()
{
    printf("**A:查快递**\n");
    printf("**E:送快递**\n");
    printf("**U:修改用户信息**\n");
    printf("**H:查询历史订单记录**\n");
    printf("**Q:返回上一级菜单**\n");
}

/**
 * @brief 客户端注册
 * 用户输入用户名和密码
 * 封装消息
 * 发送
 * 接收并输出结果
 */
void Register(PACK *msg)
{
    printf("请输入用户名:");
    fgets(msg->name, sizeof(msg->name), stdin);
    if (msg->name[strlen(msg->name) - 1] == '\n')
        msg->name[strlen(msg->name) - 1] = '\0';
    printf("请输入密码:");
    fgets(msg->paaswd, sizeof(msg->paaswd), stdin);
    if (msg->paaswd[strlen(msg->paaswd) - 1] == '\n')
        msg->paaswd[strlen(msg->paaswd) - 1] = '\0';
    printf("name:%s  pass:%s\n", msg->name, msg->paaswd);
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

/**
 * @brief 客户端登录
 * 用户输入用户名和密码
 * 封装消息
 * 发送
 * 接收并输出结果
 *
 */
void Login(PACK *msg)
{
    while (1)
    {
        printf("请输入用户名:");
        // fgets(msg->name, sizeof(msg->name), stdin);
        // if (msg->name[strlen(msg->name) - 1] == '\n')
        //     msg->name[strlen(msg->name) - 1] = '\0';
        scanf("%s", msg->name);
        getchar();
        printf("请输入密码:");
        // fgets(msg->paaswd, sizeof(msg->paaswd), stdin);
        // if (msg->paaswd[strlen(msg->paaswd) - 1] == '\n')
        //     msg->paaswd[strlen(msg->paaswd) - 1] = '\0';
        scanf("%s", msg->paaswd);
        getchar();

        send(sockfd, msg, sizeof(PACK), 0);
        recv(sockfd, msg, sizeof(PACK), 0);

        if (strcmp(msg->buf, "登录成功") == 0)
        {
            printf("%s\n\n", msg->buf);
            flag = 1;
            break;
        }
        else
        {
            printf("%s\n\n", msg->buf);
        }
    }
    return;
}

/**
 * @brief 客户端送快递
 * 用户输入要送达的快递单号
 * 封装消息
 * 发送
 * 接收并输出结果
 *
 */

void Send_express(PACK *msg)
{
    printf("请输入要送达的快递单号:");
    scanf("%ld", &(msg->msgg.order));
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

/**
 * @brief 客户端查询快递状态
 * 输入要查询订单号
 * 发送
 * 接收并输出查询结果
 */
void Search_status(PACK *msg)
{
    char sql[1024] = {0};
    printf("请输入要查询的订单号:");
    scanf("%ld", &(msg->msgg.order));
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, sql, sizeof(sql), 0);
    if (strcmp(sql, "1") == 0)
    {
        printf("已送达\n\n");
    }
    else
    {
        printf("未送达\n\n");
    }
    return;
}

/**
 * @brief 客户端修改用户信息
 * 输入要修改的密码
 * 发送
 * 接收并输出结果
 */
void Change_user(PACK *msg)
{
    printf("请输入要修改的用户名:");
    scanf("%s", msg->name);
    getchar();
    printf("请输入要修改的密码:");
    scanf("%s", msg->paaswd);
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

/**
 * @brief 客户端注销用户信息
 * 输入要注销的用户名、密码
 * 发送
 * 接收并输出结果
 */
void Delete_user(PACK *msg)
{
    printf("请输入要删除的用户名:");
    scanf("%s", msg->name);
    getchar();
    printf("请输入密码:");
    scanf("%s", msg->paaswd);
    getchar();
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, msg, sizeof(PACK), 0);
    printf("%s\n\n", msg->buf);
    return;
}

/**
 * @brief 客户端查询历史订单
 * 输入要查询的选项,查询所有订单还是根据时间戳查询
 * 发送
 * 接收并输出查询结果
 */
void Histroy(PACK *msg)
{
    char sql[1024];
    printf("请输入要查询的选项:\n");
    printf("注意:输入all查询所有订单 或 输入time:(要查询的时间):\n");
    memset(msg->buf, 0, 128);
    // scanf("%s", msg->buf);
    fgets(msg->buf, 128, stdin);
    if (msg->buf[strlen(msg->buf) - 1] == '\n')
        msg->buf[strlen(msg->buf) - 1] = '\0';
    send(sockfd, msg, sizeof(PACK), 0);
    recv(sockfd, sql, sizeof(sql), 0);
    if (strcmp(sql, "查询失败") != 0)
    {
        printf("订单状态 订单号 寄出时间 送达时间\n");
        printf("%s\n\n", sql);
    }
    else
    {
        printf("%s\n", sql);
    }
}

【4】头文件

#ifndef __HEAD_H__
#define __HEAD_H__


#include<stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <sys/select.h>
#include <pthread.h>
#include <sqlite3.h>
#include <errno.h>
#include <netinet/tcp.h>

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;          //快递费用
};

typedef struct pack_head
{
    int acceptfd;
    unsigned char type;     //消息类型
    unsigned char usertype; //用户类型:1:用户  2:快递员
    char name[32];          //用户名
    char paaswd[32];        //密码
    char buf[32];           //调试信息
    struct order_msg msgg;  //单号信息
} PACK;

#endif

【5】makefile

all:
	gcc server.c -o s -lsqlite3
	gcc d_client.c -o d 
	gcc u_client.c -o u 

.PHONY:clean
clean:
	rm -f *.o

今天的分享就到这里结束啦,如果有哪里写的不好的地方,请指正。
如果觉得不错并且对你有帮助的话点个关注支持一下吧!

标签:void,编程,华清,速递,sql,printf,msg,sizeof,PACK
From: https://blog.csdn.net/dghbs/article/details/142467623

相关文章

  • Go 语言编程极简教程 2
    Go语言编程极简教程2我将为您提供一个Go语言编程的极简教程。我会尽量详细地解释每个步骤,并探讨多种方法来介绍这个主题。让我们开始吧!文章目录Go语言编程极简教程2介绍Go语言安装Go语言环境创建第一个Go程序解释Go程序结构Go语言的基本数据类型变量声......
  • 高级QML编程技巧
    高级QML编程技巧使用AI技术辅助生成QT界面美化视频课程QT性能优化视频课程QT原理与源码分析视频课程QTQMLC++扩展开发视频课程免费QT视频课程您可以看免费1000+个QT技术视频免费QT视频课程QT统计图和QT数据可视化视频免费看免费QT视频课程QT性能优化视频免费看免费Q......
  • QML与WebGL的交互编程
    QML与WebGL的交互编程使用AI技术辅助生成QT界面美化视频课程QT性能优化视频课程QT原理与源码分析视频课程QTQMLC++扩展开发视频课程免费QT视频课程您可以看免费1000+个QT技术视频免费QT视频课程QT统计图和QT数据可视化视频免费看免费QT视频课程QT性能优化视频......
  • QML与WebGL的交互编程
    QML与WebGL的交互编程使用AI技术辅助生成QT界面美化视频课程QT性能优化视频课程QT原理与源码分析视频课程QTQMLC++扩展开发视频课程免费QT视频课程您可以看免费1000+个QT技术视频免费QT视频课程QT统计图和QT数据可视化视频免费看免费QT视频课程QT性能优化视频免费看......
  • 想要转行到互联网行业,是应该选择软件工程还是网络安全?_网络工程和网络空间安全谁更适
    学习路线:这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成黑客大神,这个方向越往后,需要学习和掌握的东西就会越来越多以下是网络渗透需要学习的内容:网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄......
  • ROS 编程入门的介绍
    2.1创建ROS功能包ROS(RobotOperatingSystem)是一种开源的机器人软件框架,广泛用于机器人开发中。通过使用ROS,开发者可以轻松创建和管理机器人应用程序。在本节中,我们将介绍如何创建一个ROS功能包并实现一些基本功能。2.1.1使用ROS主题ROS主题(Topic)是一种发布/订阅机制,允许......
  • 【Linux】Shell 编程规范及检查工具推荐
    本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口| 精选文章 | Kubernetes |Docker |Linux |羊毛资源 | 工具推荐 |往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决......
  • 带你0到1之QT编程:十七、Http协议实战,实现一个简单服务器和一个客户端进行http协议通信
    此为QT编程的第十七谈!关注我,带你快速学习QT编程的学习路线!每一篇的技术点都是很很重要!很重要!很重要!但不冗余!我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点!码农不易,各位学者学到东西请点赞支持支持!开始部分:总:此次实战主要是模拟一个http协议进行网络通信的一......
  • 带你0到1之QT编程:十八、最简单之TCP协议工作原理及实战编程
    此为QT编程的第十八谈!关注我,带你快速学习QT编程的学习路线!每一篇的技术点都是很很重要!很重要!很重要!但不冗余!我们通常采取总-分-总和生活化的讲解方式来阐述一个知识点!码农不易,各位学者学到东西请点赞支持支持!开始部分:总:此次实战主要是实现一个客户端,一个服务端,来了解TC......
  • 【Python高级编程案例】-第1课时-Python 自带邮件模块自动发送邮件
    importrandomimportstringfromsmtplibimportSMTP_SSLfromemail.mime.textimportMIMETextfromemail.headerimportHeader#发送邮件,参数为收件邮箱地址和验证码defsend_email(receiver,code):sender="测试<[email protected]>"#邮箱账号,签名#......