学习嵌入式网络编程阶段,做了一个网络点餐的小项目。
功能:
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;
}