1.需求分析
随着社会经济的发展和消费者需求的多样化,自助售卖系统在商业、公共场所等领域的应用越来越广泛,市场需求不断增长。而盲盒自助售卖机受到越来越多年轻人的喜欢,让年轻人可以更方便的购买自己喜欢的盲盒。
2.项目描述
项目主要分为三个模块,分别是服务端、客户端以及数据库。服务端与客户端的通信用的是tcp协议,数据库用的是sqlite3,。主要实现的功能是服务端可以并发处理客户端的请求。客户端可以对盲盒商品进程添加、删除、查看、修改等功能。服务端响应客户端的请求。
3.功能模块
3.1.server
用的tcp传输协议框架实现的,设置了通道属性,可以重复利用端口号。并且使用select函数实现并发服务器。
3.2.client
用的tcp传输协议框架实现的。
3.3.数据库
创建了两张表,用户表user和商品信息表goods,用户表中存储用户的用户名和密码,商品信息表中存储商品的名字和数量。
readme
1.代码编译指令
服务端:
编译:gcc tcp_server.c sqlite3.c sqlite3.h -o server -lpthread -ldl
运行:./server
客户端:
编译:gcc tcp_client.c -o client
运行:./client
2.执行顺序
先运行服务端在运行客户端
3.操作说明
按功能选项就会进入功能,然后输入提示的字符串格式,就会实现相应的功能,退出按ctrl+c
以下的具体代码
server.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include "sqlite3.h"
#include <stdlib.h>
#define BUF_SIZE 1024
#define SIZE 20
#define SQL_SIZE 50
struct sqlite3 *g_db = NULL;
//字符串解析函数
int stringjiexi(char buf[],char (*pmsg)[SIZE])
{
char *p = NULL;
int count = 0;
if(buf == NULL)
{
return -1;
}
else
{
p = strtok(buf,"#");
strcpy(*pmsg,p);
count++;
while(1)
{
p = strtok(NULL,"#");
if(p != NULL)
{
pmsg++;
strcpy(*pmsg,p);
count++;
}
else
{
break;
}
}
}
return count;
}
//register函数
int registerdb(char str1[],char str2[])
{
char sql[SQL_SIZE] = {0};
sprintf(sql,"insert into user(name,password) values('%s','%s')",str1,str2);
int ret = sqlite3_exec(g_db,sql,0,0,NULL);
if(0 != ret )
{
//printf("insert error!\r\n");
return -1;
}
//printf("insert ok!\r\n");
return 0;
}
//load函数
int loaddb(char str1[])
{
char sql[SQL_SIZE] = {0};
sprintf(sql,"select * from user where name='%s'",str1);
int ret = sqlite3_exec(g_db,sql,0,0,NULL);
if(0 != ret)
{
return -1;
}
return 0;
}
//insert函数
int insertdb(char str1[],int a)
{
char sql[SQL_SIZE] = {0};
sprintf(sql,"insert into goods(mname,count) values('%s',%d)",str1,a);
int ret = sqlite3_exec(g_db,sql,0,0,NULL);
if(0 != ret)
{
return -1;
}
return 0;
}
//select函数
int selectdb(char str[],char buf[BUF_SIZE])
{
char sql[SQL_SIZE] = {0};
char **resulttable = NULL;
int pRow = 0;
int pColumn = 0;
sprintf(sql,"select *from %s",str);
int ret = sqlite3_get_table(g_db,sql,&resulttable,&pRow,&pColumn,NULL);
if(0 != ret)
{
return -1;
}
printf("-------------------------\r\n");
memset(buf,0,BUF_SIZE);
int index = 0;
//打印表
for(int i = 0; i <= pRow ; i++)
{
for(int j = 0; j < pColumn; j++)
{
//printf("%s ",resulttable[i*pColumn+j]);
strcat(resulttable[index],"\t");
strcat(buf,resulttable[index]);
index++;
}
strcat(buf,"\n");
//printf("\r\n");
}
printf("%s\r\n",buf);
printf("-------------------------\r\n");
//printf("%d\r\n",**resulttable);
return 0;
}
//delete函数
int deletedb(int a,char str[])
{
char sql[SQL_SIZE] = {0};
sprintf(sql,"update goods set count=%d where mname='%s'",a,str);
int ret = sqlite3_exec(g_db,sql,0,0,NULL);
if(0 != ret)
{
return -1;
}
return 0;
}
//delete a row函数
int deletedbrow(int a)
{
char sql[SQL_SIZE] = {0};
sprintf(sql,"delete from goods where id=%d",a);
int ret = sqlite3_exec(g_db,sql,0,0,NULL);
if(0 != ret)
{
return -1;
}
return 0;
}
int main()
{
//open database
int db_ret = sqlite3_open("./mysqlite.db",&g_db);
if(0 == db_ret)
{
printf("open database ok!\r\n");
}
//1.socket
int iServer = socket(AF_INET, SOCK_STREAM,0);
if(-1 ==iServer)
{
printf("socket error!\r\n");
return -1;
}
printf("1.socket ok!\r\n");
//2.bind
int on = 1;
setsockopt(iServer,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on));
struct sockaddr_in stServer;
stServer.sin_family = AF_INET;
stServer.sin_port = htons(8888);
stServer.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = bind(iServer,(struct sockaddr *)&stServer,sizeof(struct sockaddr));
if(-1 == ret)
{
printf("bind error\r\n");
return -1;
}
printf("2.bind ok!\r\n");
//3.listen
ret = listen(iServer, 5);
if(-1 == ret)
{
printf("listen error\r\n");
return -1;
}
printf("3.listen ok!\r\n");
//4.select
fd_set stFdr;
FD_ZERO(&stFdr);
FD_SET(iServer,&stFdr);
int max = iServer;
struct sockaddr_in stClient;
socklen_t len = sizeof(struct sockaddr);
char buf[BUF_SIZE] = {0};
memset(buf,0, BUF_SIZE);
while(1)
{
fd_set stFdrTmp = stFdr;
ret = select(max+1,&stFdrTmp,NULL,NULL,NULL);
if(ret < 0)
{
printf("select error\r\n");
continue;
}
printf("4.select ok! ret = %d\r\n",ret);
for(int i=0 ; i < max+1 ;i++)
{
if(FD_ISSET(i,&stFdrTmp))
{
if(i == iServer)
{
int iClient = accept(iServer,(struct sockaddr *)&stClient,&len);
if(-1 == iClient)
{
printf("accept error\r\n");
continue;
}
printf("accept client ok! iClient = %d\r\n",iClient);
FD_SET(iClient,&stFdr);
if(max < iClient)
{
max = iClient;
}
}
else
{
ret = recv(i,buf,BUF_SIZE,0);
if(ret > 0)
{
printf("recv:%s",buf);
int opt = atoi(buf);
char msg[SIZE][SIZE] = {0};
int count = 0;
switch(opt)
{
case 1:
printf("----------------------------\r\n");
printf("register\r\n");
strcpy(buf,"register#name#passward");
send(i,buf,BUF_SIZE,0);
recv(i,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
//调用字符串解析函数
count = stringjiexi(buf,msg);
/*printf("%d\r\n",count);
for(int i=0;i<count;i++)
{
printf("%s\r\n",msg[i]);
}*/
//调用register函数
ret = registerdb(msg[1],msg[2]);
if(0 != ret)
{
printf("insert table user error\r\n");
return -1;
}
printf("insert table user ok!\r\n");
printf("----------------------------\r\n");
//发送register ok
memset(buf,0,BUF_SIZE);
strcpy(buf,"register ok!");
send(i,buf,BUF_SIZE,0);
break;
case 2:
printf("-----------------------------\r\n");
printf("load\r\n");
strcpy(buf,"load#name#passward");
send(i,buf,BUF_SIZE,0);
recv(i,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
//调用字符串解析函数
count = stringjiexi(buf,msg);
/*printf("%d\r\n",count);
for(int i=0;i<count;i++)
{
printf("%s\r\n",msg[i]);
}*/
//调用load函数
ret = loaddb(msg[1]);
if(0 != ret)
{
printf("load error\r\n");
return -1;
}
printf("load ok!\r\n");
printf("-----------------------------\r\n");
//发送load ok
memset(buf,0,BUF_SIZE);
strcpy(buf,"load ok!");
send(i,buf,BUF_SIZE,0);
break;
case 3:
printf("-----------------------------\r\n");
printf("insert\r\n");
strcpy(buf,"insert#mname#count");
send(i,buf,BUF_SIZE,0);
recv(i,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
//调用字符串解析函数
stringjiexi(buf,msg);
//调用insert函数
int a = 0;
a = atoi(msg[2]);
ret = insertdb(msg[1],a);
if(0 != ret)
{
printf("insert goods error\r\n");
return -1;
}
printf("insert table goods ok!\r\n");
printf("-----------------------------\r\n");
//发送insert ok
memset(buf,0,BUF_SIZE);
strcpy(buf,"insert table goods ok!");
send(i,buf,BUF_SIZE,0);
break;
case 4:
printf("-----------------------------\r\n");
printf("select\r\n");
strcpy(buf,"select#bname");
send(i,buf,BUF_SIZE,0);
recv(i,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
//调用字符串解析函数
stringjiexi(buf,msg);
//调用select函数
memset(buf,0,BUF_SIZE);
ret = selectdb(msg[1],buf);
if(0 != ret)
{
printf("select table error\r\n");
return -1;
}
printf("select table ok!\r\n");
//printf("%s\r\n",resulttable);
//printf("-----------------------------\r\n");
//发送表
send(i,buf,BUF_SIZE,0);
break;
case 5:
printf("------------------------------\r\n");
printf("delete\r\n");
strcpy(buf,"delete#mname#count");
send(i,buf,BUF_SIZE,0);
recv(i,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
//调用字符串解析函数
stringjiexi(buf,msg);
//调用delete函数
int b = atoi(msg[2]);
b--;
ret = deletedb(b,msg[1]);
if(0 !=ret)
{
printf("delete goods error\r\n");
return -1;
}
printf("delete goods ok!\r\n");
printf("-------------------------------\r\n");
//发送delete ok
memset(buf,0,BUF_SIZE);
strcpy(buf,"delete ok!");
send(i,buf,BUF_SIZE,0);
break;
case 6:
printf("------------------------------\r\n");
printf("delete a row\r\n");
strcpy(buf,"delete#mname#id");
send(i,buf,BUF_SIZE,0);
recv(i,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
//调用字符串解析函数
stringjiexi(buf,msg);
//调用delete函数
int c = atoi(msg[2]);
ret = deletedbrow(c);
if(0 !=ret)
{
printf("delete goods error\r\n");
return -1;
}
printf("delete goods ok!\r\n");
printf("-------------------------------\r\n");
//发送delete ok
memset(buf,0,BUF_SIZE);
strcpy(buf,"delete a row ok!");
send(i,buf,BUF_SIZE,0);
break;
default:
printf("功能选项错误\r\n");
}
}
else
{
close(i);
FD_CLR(i,&stFdr);
}
}
}
}
}
return 0;
}
client.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define BUF_SIZE 1024
int main()
{
//1.socket
int iClient = socket(AF_INET, SOCK_STREAM, 0);
if(-1 == iClient)
{
printf("socket error\r\n");
return -1;
}
printf("1.socket ok\r\n");
//2.connect
struct sockaddr_in stServer;
stServer.sin_family = AF_INET;
stServer.sin_port = htons(8888);
stServer.sin_addr.s_addr = inet_addr("127.0.0.1");
int ret = connect(iClient,(struct sockaddr *)&stServer,sizeof(struct sockaddr));
if(-1 == ret)
{
printf("connect error!\r\n");
return -1;
}
printf("2.connect ok!\r\n");
//3.send/recv
char buf[BUF_SIZE] = {0};
while(1)
{
memset(buf,0,BUF_SIZE);
printf("-----------------\r\n");
printf("1.register\r\n");
printf("2.load\r\n");
printf("3.insert\r\n");
printf("4.select\r\n");
printf("5.delete\r\n");
printf("6.delete a row\r\n");
printf("-----------------\r\n");
printf("请输入功能选项\r\n");
fgets(buf,BUF_SIZE,stdin);
send(iClient,buf,BUF_SIZE,0);
recv(iClient,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
memset(buf,0,BUF_SIZE);
fgets(buf,BUF_SIZE,stdin);
send(iClient,buf,BUF_SIZE,0);
memset(buf,BUF_SIZE,0);
printf("-------------------\r\n");
recv(iClient,buf,BUF_SIZE,0);
printf("%s\r\n",buf);
}
return 0;
}