1、项目名称
图书借阅系统
2、项目需求
对于图书馆中的书籍信息的管理,可以增、删、改、查书籍的信息,完成借阅、归还书籍的要求。
3、项目功能
1、采用并发服务器,可以同时处理多个客户端的请求。
2、客户端先注册、登录账号
3、登陆成功后可以增加、删除、查看书的信息
4、查阅、归还书籍
4、开发平台:
开发环境:Linux操作系统
开发语言:C语言
5、需求分析:
1、服务器和客户端采用TCP通信协议
2、服务器采用IO多路复用的并发服务器
3、客户端发送一长串消息给服务器,服务器解析分出有用信息后,对Sqlite3数据库的数据操作
6、项目框架
服务器启动流程
Init_net 初始化网络
Socket
Bind
Listen
将需要监听的文件描述符加入相应的文件描述符集合
Accept 等待连接请求
Send/recv 成功连接后执行操作
Close 关闭服务器
客户端启动流程
Socket
Connect 发送连接请求,成功则表明已连接至服务器
Send、recv 发送操作请求
Close
服务器与客户端交互流程
在客户端成功连上服务器后。
服务器发送一级菜单
Menu
-----1登录-----
-----2注册-----
-----0退出-----
客户端收到菜单后,根据需求发送不同cmd
服务器根据不同cmd 执行不同的操作
当客户端发送注册命令后,服务器打开账号信息数据库,添加新的账号,密码。
当客户端发送登录命令后,服务器提示客户端输入账号密码,当接收到账号密码后,服务器端打开账号信息数据库,查找账号,返回密码信息,判断输入密码与返回的密码信息,相等则服务器返回成功登录,不等则返回密码错误,重新输入的字样。
在成功登录后,客户端即可以发送增删查改的请求,服务器接收后,根据请求对书籍信息数据库执行不同操作。
7、服务器搭建
#include "../../include/ser.h"
char buf[1024];
int main()
{
int listenfd = init_net(8888);
if(listenfd < 0)
{
puts("init net error.");
return -1;
}
fd_set tempfds, readfds;
FD_ZERO(&tempfds);
FD_ZERO(&readfds);
FD_SET(listenfd, &readfds);
while(1)
{
tempfds = readfds;
int ret = select(FD_SETSIZE, &tempfds, NULL, NULL, NULL);
if(ret > 0)
{
int i = 0;
for(i = 3; i < FD_SETSIZE; i++)
{
if(FD_ISSET(i, &tempfds))
{
if(i == listenfd)
{
struct sockaddr_in mycli;
int len = sizeof(mycli);
int connfd = -1;
connfd = accept(listenfd, (struct sockaddr *)&mycli, &len);
if(connfd > 0)
{
int flags = fcntl(connfd, F_GETFL);
fcntl(connfd, F_SETFL, flags | O_NONBLOCK);
FD_SET(connfd, &readfds);
puts("a client accept success.");
}
}
else
{
memset(buf, 0, sizeof(buf));
ret = recv(i, buf, sizeof(buf), 0);
puts(buf);
if(ret > 0)
{
char ID[20] = {0};
char account[20] = {0};
char passwd[20] = {0};
char cmd[20] = {0};
char status[20] = {0};
char name[20];
char address[20];
memset(cmd,0,20);
getCmd(cmd,buf);
if(strcmp(cmd,"log") == 0)
{
memset(account,0,20);
memset(passwd,0,20);
getAccount(account, buf);
getPasswd(passwd,buf);
login(i,account,passwd);
}
if(strcmp(cmd, "reg") == 0)
{
memset(account,0,20);
memset(passwd,0,20);
getAccount(account, buf);
getPasswd(passwd,buf);
//puts("我要写入数据了");
regin(i,account,passwd);
}
if(strcmp(cmd,"sek") == 0)
{
memset(ID,0,20);
getID(ID,buf);
ret = check_ID_exist(ID);
if(ret == 0)
{
sek_book_info(i,ID);
}
else
{
send(i,"库中查无此id",50,0);
}
}
if(strcmp(cmd,"add") == 0)
{
memset(ID,0,20);
memset(status,0,20);
memset(name,0,20);
memset(address,0,20);
getID(ID,buf);
get_msg(buf,name,address,status);
add_book_info(i,ID,name,address,status);
}
if(strcmp(cmd,"del") == 0)
{
memset(ID,0,20);
getID(ID,buf);
ret = check_ID_exist(ID);
if(ret == 0)
{
del_book_info(i,ID);
}
else
{
send(i,"库中查无此id",50,0);
}
}
if(strcmp(cmd,"rev") == 0)
{
memset(ID,0,20);
getID(ID,buf);
memset(status,0,20);
getstatus(status,buf);
puts(ID);
puts(status);
ret = check_ID_exist(ID);
if(ret == 0)
{
rev_book_info(i,ID,status);
}
else
{
send(i,"库中查无此id",50,0);
}
}
}
else if(ret == 0)
{
FD_CLR(i, &readfds);
close(i);
puts("a client exit.");
}
else
{
continue;
}
}
}
}
}
}
close(listenfd);
return 0;
}
#include "../../include/ser.h"
char msg[255] = {0};
char buf[1024];
char success_buf[20] = "success";
char error_buf[20] = "error";
int init_net(unsigned short port)
{
int serfd = -1;
serfd = socket(AF_INET, SOCK_STREAM, 0);
if(serfd < 0)
{
puts("socket error.");
return -1;
}
puts("socket success.");
struct sockaddr_in myser;
memset(&myser, 0, sizeof(myser));
myser.sin_family = AF_INET;
myser.sin_port = htons(port);
myser.sin_addr.s_addr = htonl(INADDR_ANY);
int ret = bind(serfd, (struct sockaddr *)&myser, sizeof(myser));
if(ret != 0)
{
puts("bind error.");
close(serfd);
return -1;
}
puts("bind success.");
ret = listen(serfd, 5);
if(ret != 0)
{
puts("listen error.");
close(serfd);
return -1;
}
int flags = fcntl(serfd, F_GETFL);
fcntl(serfd, F_SETFL, flags | O_NONBLOCK);
return serfd;
}
int getstatus(char *status,char *buf)
{
if(NULL == status || NULL == buf)
{
puts("NULL pointer error");
return ERROR;
}
memcpy(status,buf+11,20);
return OK;
}
int getAccount(char *Account,char *login_buf)
{
if(NULL == Account || NULL == login_buf)
{
puts("NULL pointer error");
return ERROR;
}
memcpy(Account,login_buf+4,6);
return OK;
}
int getID(char *ID,char *buf)
{
if(NULL == ID || NULL == buf)
{
puts("NULL pointer error");
return ERROR;
}
memcpy(ID,buf+4,6);
return OK;
}
int getPasswd(char *Passwd,char *login_buf)
{
if(NULL == Passwd || NULL == login_buf)
{
puts("NULL pointer error");
return ERROR;
}
memcpy(Passwd,login_buf+11,6);
return OK;
}
int getCmd(char *cmd,char *buf)
{
if(NULL == cmd || NULL == buf)
{
puts("NULL pointer error");
return ERROR;
}
memcpy(cmd,buf,3);
return OK;
}
int login(int connfd,char *Account,char *Passwd)
{
sqlite3 *pdb;
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char data[100] = {0};
char sql[255] = {0};
sprintf(sql,"select Passwd from usr_info where Account = %s; ",Account);
sqlite3_exec(pdb, sql, get_passwd, data, &errmsg);
if(errmsg)
{
puts(errmsg);
sqlite3_close(pdb);
return -1;
}
if(strcmp(data,Passwd) == 0)
{
puts("验证成功");
send(connfd,success_buf,50,0);
}
else
{
puts("未通过验证");
send(connfd,error_buf,50,0);
}
sqlite3_close(pdb);
return 0;
}
int regin(int connfd,char *Account,char *Passwd)
{
sqlite3 *pdb;
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char data[100] = {0};
char sql[255] = {0};
sprintf(sql,"INSERT INTO usr_info (Account,Passwd) VALUES(%s,%s);",Account,Passwd);
puts(sql);
if(sqlite3_exec(pdb, sql, NULL, 0, &errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
}
else
{
puts("注册完成");
send(connfd,"reg_success",50,0);
}
sqlite3_close(pdb);
return 0;
}
int sek_book_info(int connfd,char *ID)
{
sqlite3 *pdb;
char ret_buf[255] = {0};
char data[100];
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char sql[255] = {0};
sprintf(sql,"select * from book where ID = %s ;",ID);
if(sqlite3_exec(pdb, sql, callback, NULL, &errmsg ) != SQLITE_OK)
{
printf("%s\n", errmsg);
sqlite3_close(pdb);
return -1;
}
else
{
printf("成功读取数据.\n");
send(connfd,msg,sizeof(msg),0);
}
sqlite3_close(pdb);
return 0;
}
int callback(void *para, int f_num, char **f_value, char **f_name)
{
int i = 0;
memset(msg,0,sizeof(msg));
for(i = 0; i < f_num; i++)
{
printf("%-11s ", f_value[i]);
strcat(msg,f_value[i]);
}
printf("\n");
return 0;
}
static int get_passwd(void *data,int argc,char **argv,char **column_name)
{
if(NULL == data)
{
return ERROR;
}
if(argc == 1)
{
strcpy(data,argv[0]);
}
return OK;
}
int del_book_info(int connfd,char *ID)
{
sqlite3 *pdb;
char ret_buf[255] = {0};
char data[100];
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char sql[255] = {0};
sprintf(sql,"delete from book where ID = %s ;",ID);
if(sqlite3_exec(pdb, sql, NULL, 0, &errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
}
else
{
puts("删除完成");
sqlite3_close(pdb);
send(connfd,"success",50,0);
}
return 0;
}
int rev_book_info(int connfd,char *ID,char *status)
{
sqlite3 *pdb;
char ret_buf[255] = {0};
char data[100];
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char sql[255] = {0};
sprintf(sql,"UPDATE book set STATUS = '%s' where ID = %s ;",status,ID);
puts(sql);
if(sqlite3_exec(pdb, sql, NULL, 0, &errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
}
else
{
puts("修改完毕");
send(connfd,"success",50,0);
}
sqlite3_close(pdb);
return 0;
}
int get_msg(char *buf,char *name,char *address,char *status)
{
if(NULL == buf || NULL == name || NULL == address || NULL == status)
{
puts("入参错误");
return ERROR;
}
char *temp = NULL;
char *p = buf;
p = p + 11;
while(1)
{
if(':' == *p)
{
break;
}
else
{
*name = *p;
name += 1;
p += 1;
}
}
char *q = p+1;
while(1)
{
if(':' == *q)
{
break;
}
else
{
*address = *q;
address += 1;
q += 1;
}
}
strcpy(status,q+1);
return 0;
}
int add_book_info(int connfd,char *ID,char *name,char *address,char *status)
{
if(NULL == ID || NULL == name || NULL == address || NULL == status)
{
puts("入参错误");
return ERROR;
}
sqlite3 *pdb;
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char data[100] = {0};
char sql[255] = {0};
memset(sql,0,sizeof(sql));
sprintf(sql,"INSERT INTO book (ID,NAME,ADDRESS,STATUS) VALUES(%s,'%s','%s','%s');",ID,name,address,status);
if(sqlite3_exec(pdb, sql, NULL, 0, &errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
return ERROR;
}
sqlite3_close(pdb);
send(connfd,"success",50,0);
return OK;
}
int check_ID_exist(char *ID)
{
sqlite3 *pdb;
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char data[100] = {0};
char sql[255] = {0};
sprintf(sql,"select ID from book where ID like %s ;",ID);
sqlite3_exec(pdb, sql, get_passwd, data, &errmsg);
if(errmsg)
{
puts(errmsg);
sqlite3_close(pdb);
return -1;
}
if(strcmp(data,ID) == 0)
{
sqlite3_close(pdb);
return 0;
}
else
{
sqlite3_close(pdb);
return -1;
}
}
int check_Account_exist(char *Account)
{
sqlite3 *pdb;
char *errmsg = NULL;
sqlite3_open("lib.db",&pdb);
if(NULL == pdb)
{
puts("open db error.");
return -1;
}
puts("open db success.");
char data[100] = {0};
char sql[255] = {0};
sprintf(sql,"select Account from usr_info where Account like %s ;",Account);
sqlite3_exec(pdb, sql, get_passwd, data, &errmsg);
if(errmsg)
{
puts(errmsg);
sqlite3_close(pdb);
return -1;
}
if(strcmp(data,Account) == 0)
{
sqlite3_close(pdb);
return 0;
}
else
{
sqlite3_close(pdb);
return -1;
}
}