Linux基于tcp-celect多路复用实现网络点餐系统

        学习嵌入式网络编程阶段,做了一个网络点餐的小项目。

 功能:

        1、实现登录注册,未注册的客户只能先注册;

        2、登录成功后实现点餐;

        3、点餐后返回给客户总金额

        4、管理员能够对菜单进行增加或删除

        菜单和用户信息分别放在sqlite3 两个数据表里面,管理员账号密码是在sqlite3软件提前添加的,程序还有很多需要改进完善的地方,欢迎大佬们在评论区指正~~

服务器端

server.h
#ifndef _SERVER_H
#define _SERVER_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <poll.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sqlite3.h>

#define PORT 8888

typedef struct _MSG
{
    int code;          //存放操作码 1-注册 2-登陆  3添加 4删除 5-点单 
    char id[32];        //存放菜品id号
    char name[128];     //存放用户名或菜品名称
    char pass[128];     //存放密码或菜品价格及服务器与客户端间的通信
}msg_t;

void enroll(int connfd, sqlite3 * user, msg_t *msg);
void login(int connfd, sqlite3 * user, msg_t *msg);
void addmenu(int connfd, sqlite3 * menu, msg_t *msg);
void deletemenu(int connfd, sqlite3 * menu, msg_t *msg);
void orderdish(int connfd, sqlite3 * menu, msg_t *msg);

#endif
 server.c
#include "server.h"

//注册函数
void enroll(int connfd, sqlite3 *user, msg_t *msg)
{
    char sql[1024];
    int ret = 0;
    msg_t msg_tmp;

    sprintf(sql, "insert into user values('%s', '%s');", msg->name, msg->pass);
    if(sqlite3_exec(user, sql, NULL, NULL, NULL) == -1)  //注册失败
    {
        strcpy(msg->pass, "The name hans been used...\n");
        if(send(connfd, msg, sizeof(msg_t), 0) == -1)
        {
            perror("enroll_send_1");
            return;
        }
    }
    else        //注册成功
    {
        strcpy(msg->pass, "enroll success!!\n");
        if(send(connfd, msg, sizeof(msg_t), 0) == -1)
        {
            perror("enroll_send_2");
            return;
        }
    }
    return;
}

//登陆函数
void login(int connfd, sqlite3 * user, msg_t *msg)
{
    msg_t msg_tmp = *msg;
    char sql[1024];
    int nrow, ncount, ret;
    char *err;
    char **result = NULL;

    sprintf(sql, "select * from user where name = '%s' and passwd = '%s';", msg_tmp.name, msg_tmp.pass);
    ret = sqlite3_get_table(user, sql, &result, &nrow, &ncount, &err);
    if(ret == -1)
    {
        printf("get_table:%s\n", err);
        return;
    }
    else if(nrow == 1)      //查询到相关用户信息
    {
        memset(&msg_tmp, 0, sizeof(msg_t));
        sprintf(msg_tmp.pass, "log success!!\n");
        if(send(connfd, &msg_tmp, sizeof(msg_t), 0) == -1)
        {
            perror("login_sen");
            return;
        }
    }
    else                //未查询到相关信息,用户名或密码错误
    {
        memset(&msg_tmp, 0, sizeof(msg_t));
        sprintf(msg_tmp.pass, "name or password error!!\n");
        if(send(connfd, &msg_tmp, sizeof(msg_t), 0) == -1)
        {
            perror("login_sen");
            return;
        }
    }
    return;
}
//添加菜单
void addmenu(int connfd, sqlite3 *menu, msg_t *msg)
{
    msg_t msg_tmp = *msg;
    char sql[2048];
    int nrow, ncount, ret;
    char *err;
    char **result;

    sprintf(sql, "insert into menu values('%s', '%s', '%s');", msg_tmp.id, msg_tmp.name, msg_tmp.pass);
    ret = sqlite3_get_table(menu, sql, &result, &nrow, &ncount, &err);
    if(ret == -1)
    {
        printf("addmenu_get_table error:%s\n", err);
        return;
    }
    else
    {
        memset(&msg_tmp, 0, sizeof(msg_t));
        strcpy(msg_tmp.pass, "addmenu success!!\n");
        if(send(connfd, &msg_tmp, sizeof(msg_t), 0) == -1)
        {
            perror("addmenu_send");
            return;
        }
    }
    return;
}

//删除菜单
void deletemenu(int connfd, sqlite3 *menu, msg_t *msg)
{
    msg_t msg_tmp = *msg;
    char sql[2048];
    int nrow, ncount, ret;
    char *err;
    char **result;

    sprintf(sql, "delete from menu where name = '%s';", msg_tmp.pass);
    ret = sqlite3_get_table(menu, sql, &result, &nrow, &ncount, &err);
    if(ret == -1)
    {
        printf("deletemenu get_table error:%s\n", err);
        return;
    }
    else
    {
        memset(&msg_tmp, 0, sizeof(msg_t));
        strcpy(msg_tmp.pass, "deletemenu success!!\n");
        if(send(connfd, &msg_tmp, sizeof(msg_t), 0) == -1)
        {
            perror("deletemenu_send");
            return;
        }
    }
    return;
}

//点单
void orderdish(int connfd, sqlite3 *menu, msg_t *msg)
{
    msg_t msg_tmp = *msg;
    char sql[2048];
    int nrow, ncount, ret, price = 0;
    char *err;
    char **result;

    for(int i = 0; i < strlen(msg_tmp.pass); i++)
    {
        sprintf(sql, "select * from menu where id = '%c';", msg_tmp.pass[i]);
        ret = sqlite3_get_table(menu, sql, &result, &nrow, &ncount, &err);
        if(ret == -1)
        {
            printf("orderdish get_table:%s\n", err);
            exit(-1);
        }
        if(nrow * ncount == 0)
            continue;
        else
            price = price + atoi(result[5]);
    }
    memset(&msg_tmp, 0, sizeof(msg_t));
    sprintf(msg_tmp.pass, "orderdish success!! the sum of price is %d RMB, plese pay!!\n", price);
    if(send(connfd, &msg_tmp, sizeof(msg_t), 0) == -1)
    {
        perror("orderdish_send\n");
        return;
    }
    return;

}
 main.c
#include "server.h"

int main(int argc, char *argv[])
{ 
    int ret;
    msg_t msg = {0};
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("socket");
        return -1;
    }

    struct sockaddr_in seraddr;
    seraddr.sin_family = AF_INET;
    seraddr.sin_port = htons(PORT);
    seraddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    socklen_t acclen = sizeof(seraddr);

    if(bind(sockfd, (struct sockaddr *)&seraddr, sizeof(seraddr)) == -1)
    {
        perror("bind");
        return -1;
    }

    if(listen(sockfd, 8) == -1)
    {
        perror("listen");
        return -1;
    }
#if 0
    struct pollfd fds[1024];
    int i, len = 0;
    for(i = 0; i < 1024; i++)
    {
        fds[i].fd = -1;
    }
    fds[len].fd = sockfd;
    fds[len].events = POLLIN;
    len++;
#else
    fd_set rset, tempset;
    int maxfd = sockfd;
    FD_ZERO(&rset);
    FD_SET(sockfd, &rset);

#endif
    sqlite3 *user, *menu;
    if(sqlite3_open("../client/project.db", &user) || sqlite3_open("../client/project.db", &menu) == -1)
    {
        printf("sqlite3_open");
        return -1;
    }

    while(1)
    {
        tempset = rset;
        int nready = select(maxfd+1, &tempset, NULL, NULL, NULL);
        if(nready < 0)
        {
            perror("select");
            exit(-1);
        }

        if(FD_ISSET(sockfd, &tempset))
        {
            int connfd = accept(sockfd, (struct sockaddr *)&seraddr, &acclen);
            if(connfd == -1)
            {
                perror("accept");
                exit(-1);
            }
            printf("one client connect!!\n");

            FD_SET(connfd, &rset);
            if(maxfd < connfd)
                maxfd = connfd;
            if(nready == 1)
                continue;
        }
        for(int i = sockfd + 1; i <= maxfd; i++)                //说明是通信的请求
        {
            if(FD_ISSET(i, &tempset))
            {
                if((ret = recv(i, &msg, sizeof(msg_t), 0)) == -1)
                {
                    perror("recv");
                    exit(0);
                }
                if(ret == 0)
                {
                    printf("one client exit\n");
                    FD_CLR(i, &rset);
                    close(i);
                    continue;
                }

                switch(msg.code)
                {
                    case 1:   //注册
                        enroll(i, user, &msg);
                        break;
                    case 2:   //登陆
                        login(i, user, &msg);
                        break;
                    case 3:   //添加菜单
                        addmenu(i, menu, &msg);
                        break;
                    case 4:   //删除菜单
                        deletemenu(i, menu, &msg);
                        break;
                    case 5:   //点单
                        orderdish(i, menu, &msg);
                        break;
                    case 6:   //退出
                        {
                            printf("one client exit\n");
                            FD_CLR(i, &rset);
                            close(i);
                        }
                        break;
                    default:
                        printf("choose error!!\n");
                        break;
                }
            }
        }
    }

    return 0;
} 

客户端

client.h
#ifndef _CLIENT_H
#define _CLIENT_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sqlite3.h>

#define PORT 8888

typedef struct _MSG
{
    int code;
    char id[32];
    char name[128];
    char pass[128];
}msg_t;

void printmenu1();
void printmenu2();
void printmenu3();
void enroll(int sockfd, msg_t *msg);
int login(int sockfd, msg_t *msg);
void orderdish(int sockfd, msg_t *msg);
int admin();
void addmenu(int sockfd, msg_t *msg);
void deletemenu(int sockfd, msg_t *msg);
void showmenu();
#endif
client.c
#include "client.h"

void printmenu1()
{
    printf("******************************************\n");
    printf("*1-enroll    2-login    3-admin    4-quit*\n");
    printf("******************************************\n");
}

void printmenu2()
{
    printf("******************************************\n");
    printf("*1-orderdish                     2-return*\n");
    printf("******************************************\n");
}

void printmenu3()
{
    printf("******************************************\n");
    printf("*1-addmenu      2-deletemenu     3-return*\n");
    printf("******************************************\n");
}

void enroll(int sockfd, msg_t *msg)
{
    msg->code = 1;
    msg_t msg_tmp;
    printf("please input your name:>>");
    scanf("%s", msg->name);
    printf("please input your password:>>");
    scanf("%s", msg->pass);

    if(send(sockfd, msg, sizeof(msg_t), 0) == -1)
    {
        perror("enroll_send");
        exit(-1);
    }
    if(recv(sockfd, &msg_tmp, sizeof(msg_t), 0) == -1)
    {
        perror("enroll_recv");
        exit(-1);
    }
    printf("server:%s\n", msg_tmp.pass);
    return;
}

int login(int sockfd, msg_t *msg)
{
    char buff[8192];
    msg_t msg_tmp;
    msg->code = 2;
    printf("please input your name:>>");
    scanf("%s", msg->name);
    printf("please input your password:>>");
    scanf("%s", msg->pass);

    if(send(sockfd, msg, sizeof(msg_t), 0) == -1)
    {
        perror("login_send");
        exit(-1);
    }
    if(recv(sockfd, &msg_tmp, sizeof(msg_t), 0) == -1)
    {
        perror("enroll_recv");
        exit(-1);
    }

    if(!strcmp(msg_tmp.pass, "name or password error!!\n")) //登陆失败
    {
        printf("server:%s\n", msg_tmp.pass);
        return -1;
    }
    else if(!strcmp(msg_tmp.pass, "log success!!\n"))       //登陆成功
    {
        printf("server:%s\n", msg_tmp.pass);
        return 0;
    }
}

int admin()
{
    char buf[64], buff[64];
    printf("please input admin's name:>>");
    scanf("%s", buf);
    printf("please input admin's password:>>");
    scanf("%s", buff);

    if((strcmp(buf, "xrt") == 0) && (strcmp(buff, "978") == 0))
    {
        printf("approve success!!\n");
        return 0;
    }
    else
    {
        printf("authentication failure!!\n");
        return -1;
    }
    return 0;
}

void addmenu(int sockfd, msg_t *msg)
{
    msg_t msg_tmp;
    msg->code = 3;
    printf("please input the id of the food:>>");
    scanf("%s", msg->id);
    printf("please input the name:>>");
    scanf("%s", msg->name);
    printf("please input the price:>>");
    scanf("%s", msg->pass);

    if(send(sockfd, msg, sizeof(msg_t), 0) == -1)
    {
        perror("addmenu_send");
        exit(-1);
    }
    if(recv(sockfd, &msg_tmp, sizeof(msg_t), 0) == -1)
    {
        perror("addmenu_recv");
        exit(-1);
    }
    printf("server:%s\n", msg_tmp.pass);
    return;
}

void deletemenu(int sockfd, msg_t *msg)
{
    msg_t msg_tmp;
    msg->code = 4;
    printf("please input the name of food:>>");
    scanf("%s", msg->pass);

    if(send(sockfd, msg, sizeof(msg_t), 0) == -1)
    {
        perror("addmenu_send");
        exit(-1);
    }
    if(recv(sockfd, &msg_tmp, sizeof(msg_t), 0) == -1)
    {
        perror("addmenu_recv");
        exit(-1);
    }
    printf("server:%s\n", msg_tmp.pass);
    return;
}

void orderdish(int sockfd, msg_t *msg)
{
    msg_t msg_tmp;
    msg->code = 5;
    printf("please input the id of the food:>>");
    getchar();
    fgets(msg->pass, sizeof(msg->pass), stdin);
    
    if(send(sockfd, msg, sizeof(msg_t), 0) == -1)
    {
        perror("orderdish_send");
        exit(-1);
    }
    if(recv(sockfd, &msg_tmp, sizeof(msg_t), 0) == -1)
    {
        perror("orderdish_recv");
        exit(-1);
    }
    printf("server:%s\n", msg_tmp.pass);
    return;
}

void showmenu()
{
    char sql[8192];
    sqlite3 *menu;
    int nrow, ncount;
    char *err;
    char **result;
    if(sqlite3_open("project.db", &menu) == -1)
    {
        printf("open");
        exit(-1);
    }
    sprintf(sql, "select * from menu;");

    if(sqlite3_get_table(menu, sql, &result, &nrow, &ncount, &err) == -1)
    {
        printf("get_table2: %s\n", err);
        exit(-1);
    }

    for(int i = 0; i < nrow*ncount + ncount; i+=3)
    {
        printf("%-5s%-20s%-5s\n", result[i], result[i+1], result[i+2]);
    }
}
main.c
#include "client.h"

int main(int argc, char *argv[])
{ 
    int sockfd, ret, retadmin, choose = 0;
    msg_t msg;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)
    {
        perror("socket");
        return -1;
    }

    struct sockaddr_in cliaddr;
    cliaddr.sin_family = AF_INET;
    cliaddr.sin_port = htons(PORT);
    cliaddr.sin_addr.s_addr = inet_addr("0.0.0.0");
    socklen_t conlen = sizeof(cliaddr);

    if((connect(sockfd, (struct sockaddr *)&cliaddr, sizeof(cliaddr))) == -1)
    {
        perror("connect");
        return -1;
    }

A:
    while(1)
    {
        printmenu1();
        printf("please choose:>>");
        scanf("%d", &choose);
        switch(choose)
        {
            case 1:     //注册
                enroll(sockfd, &msg);
                break;
            case 2:     //登陆
                if((ret = login(sockfd, &msg)) == -1)   //登陆失败
                    break;
                else if(ret == 0)   //登陆成功,进入二级选项
                    goto B;
            case 3:     //管理员!!!!!!!!!!!!!!!!!!*****************!!!!!!!!!!!!!!!
                retadmin = admin();
                if(retadmin == -1)//认证失败
                    break;
                else if(retadmin == 0)   //认证成功
                    goto C;
            case 4:
                close(sockfd);
                exit(0);
        }
    }

B:
    while(1)
    {
        printmenu2();
        printf("pelase choose:>>");
        scanf("%d", &choose);
        switch(choose)
        {
            case 1:     //点单
                showmenu();
                orderdish(sockfd, &msg);
                break;
            case 2:     //返回上级菜单
                goto A;
        }
    }

C:
    while(1)
    {
        printmenu3();
        printf("please choose:>>");
        scanf("%d", &choose);
        switch(choose)
        {
            case 1:     //添加菜单
                showmenu();
                addmenu(sockfd, &msg);
                break;
            case 2:     //删除菜单
                showmenu();
                deletemenu(sockfd, &msg);
                break;
            case 3:     //返回上一级
                goto A;
        }
    }

    return 0;
} 

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值