#include "server.h"
void sig_child_handle(int signo)
{
if(signo == SIGCHLD)
{
while(waitpid(-1,NULL,WNOHANG) > 0);
//一个SIGCHLD可能有多个僵尸进程,循环收尸
}
}
int main(int argc, const char *argv[])
{
if(argc != 3)
{
printf("Usage:%s serverip port.\n",argv[0]);
return -1;
}
sqlite3 *db = NULL;
char *errmsg;
//打开创建数据库
if(sqlite3_open(DATABASE,&db) != SQLITE_OK)
{
//打印得到错误的信息
printf("%s\n",sqlite3_errmsg(db));
return -1;
}
else
{
printf("open DATABASE success.\n");
}
//数据库进行操作
//第一个参数:数据库句柄
//第二个参数:Sql语句
//第三个参数:callback:回调函数,只有在查询的时候才传参
//第四个参数:为回调函数传递的参数
//第五个参数:错误信息user
//创建第一个表格,用于存放用户和密码信息
if(sqlite3_exec(db,
"create table if not exists user(name text primary key,password text);",
NULL,NULL,&errmsg)!= SQLITE_OK)
{
printf("user table:%s\n",errmsg);//失败
return -1;
}
else
{
printf("create or open user table success.\n"); //成功
}
//创建第二个表格包括:name,addr,age,phone,salary
if(sqlite3_exec(db, "create table if not exists info(no text,name text primary key,addr text,age text,phone text,work text,salary text);",NULL,NULL,&errmsg)!=SQLITE_OK)
{
printf("info table:%s\n",errmsg);
return -1;
}
else
{
printf("create or open info table success.\n");
}
//创建第三个表格,用以存储操作记录
if(sqlite3_exec(db,
"create table if not exists history(no text primary key,operation text);",
NULL,NULL,&errmsg)!= SQLITE_OK)
{
printf("history table:%s\n",errmsg);//失败
return -1;
}
else
{
printf("create or open history table success.\n"); //成功
}
//配置网络
//创建套接字
int fd = -1;
//IPV4 类型:TCP流式套接字 protocol协议
fd = socket(AF_INET,SOCK_STREAM,0);
if(-1 == fd)
{
perror("socket");
exit(1);
}
//允许绑定地址快速重用
int b_reuse = 1;
setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuse,sizeof(int));
//填充结构体
struct sockaddr_in sin;
bzero(&sin,sizeof(sin)); //对结构体进行清零
sin.sin_family = AF_INET;
//端口号 本地字节序转换为网络字节序
int a = 0;
a=atoi(argv[2]);
sin.sin_port = htons(a);
printf("服务器端口:%d\n",a);
//任意IP地址转换为网络字节序
printf("服务器IP地址:%s\n",argv[1]);
sin.sin_addr.s_addr = inet_addr(argv[1]);
//绑定IP和端口
int bind_t = bind(fd,(struct sockaddr*)&sin,sizeof(sin));
if(bind_t < 0)
{
perror("fail to bind");
exit(1);
}
//将套接字设置为监听模式
int listen_t = listen(fd,5);
if(listen_t < 0)
{
perror("fail to listen");
exit(1);
}
puts("服务器ok!");
//处理僵尸进程
signal(SIGCHLD,sig_child_handle);
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
int newfd = -1;
pid_t pid = -1;
while(1)
{
//阻塞等待用户连接
newfd = accept(fd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
perror("fail to accept");
break;
}
//链接上一个客户端就创建一个子进程,专门通讯
pid = fork();
if(pid < 0)
{
perror("fail to fork");
break;
}
//子进程
else if (pid == 0)
{
//处理客户端具体的信息
close(fd);//在子进程中关闭第一个套接字描述符
cli_info((struct sockaddr_in)cin);
do_client(newfd,db);
return 0;
}
//父进程,用来接受客户端的请求的
else
{
close(newfd);
printf("child waiting connect ......\n");
}
}
return 0;
}
void cli_info(struct sockaddr_in cin)
{
char ip[16];
const char* ntop_t;
ntop_t = inet_ntop(AF_INET,(void*)&cin.sin_addr.s_addr,ip,16);
if(NULL == ntop_t)
{
perror("ntop");
exit(1);
}
printf("客户端IP:%s 端口号:%d\n",ip,ntohs(cin.sin_port));
}
void cli_data_handle(int newfd)
{
printf("客户端 处理进程 newfd = %d\n",newfd);
int ret = -1;
char buf[BUFSIZ];
while(1)
{
bzero(buf,sizeof(buf));
ret = read(newfd,buf,BUFSIZ-1);
if(ret < 0)
{
perror("read");
exit(1);
}
if(!ret)
{
break;//双方关
}
printf("接收到:%s\n",buf);
if(!strncasecmp(buf,QUIT,4))
{
printf("客户端%d退出\n",newfd);
break;
}
}
close(newfd);
}
int do_client(int newfd,sqlite3 *db)//登录函数
{
USER user;
while(recv(newfd,&user,sizeof(user),0) > 0 )
{
printf("type:%d\n",user.type);
switch(user.type)
{
case R:
do_register(newfd,&user,db);
break;
case A:
do_login(newfd,&user,db);
break;
case D:
printf("server exit!\n");
sqlite3_close(db);//关闭数据库
close(newfd);//关闭文件描述符
exit(0);
break;
default:
printf("Invalid password user.\n");
}
}
printf("client exit .\n");
close(newfd);
exit(0);
return 0;
}
//注册函数
void do_register(int newfd,USER *user,sqlite3 *db)
{
char* errmsg;
char sql[500];
char msg[500];
//将名字和密码存入数组中
sprintf(sql,"insert into user values('%s',%s);",user->name,user->password);
printf("user:%s\n",sql);
sprintf(msg,"%s try to register",user->name);
hisinfo_into(db, msg);
memset(msg, 0, sizeof(msg));
if(sqlite3_exec(db,sql,NULL,NULL,&errmsg) != SQLITE_OK)
{
printf("%s\n",errmsg);
strcpy(user->password,"usr name already exist.");
//注册失败或者用户存在
sprintf(msg,"%s register fail",user->name);
hisinfo_into(db, msg);
memset(msg, 0, sizeof(msg));
}
else
{
printf("client register ok!\n");//注册成功
strcpy(user->password,"ok!");
}
if(send(newfd,user,sizeof(USER),0) < 0 )
{
perror("fail to send");
return ;
}
sprintf(msg,"%s register successful",user->name);
hisinfo_into(db, msg);
memset(msg, 0, sizeof(msg));
return ;
}
//登录函数
int do_login(int newfd,USER *user,sqlite3 *db)
{
char sql[500] = {};
char *errmsg;
int nrow;
int ncloumn;
char **resultp;
char msg[50];
//将名字和密码输入到Sql数组中
sprintf(sql,"select * from user where name = '%s' and password ='%s';",
user->name,user->password);
printf("*****%s\n",sql);
//非回调的方式进行select查询,是否有对应的账户和密码
if((sqlite3_get_table(db,sql,&resultp,&nrow,&ncloumn,&errmsg))!=SQLITE_OK)
{
printf("get_table:%s\n",errmsg);
return -1;
}
else
{
printf("get_table ok!\n");
}
//查询成功,数据库中拥有此用户,可以进行登录
if(nrow !=0 )
{
printf("%s login success!\n",user->name);
sprintf(msg,"%s login",user->name);
hisinfo_into(db, msg);
if((strncmp(user->name,"hjy",strlen(user->name)) == 0) &&(strncmp(user->password,"12345",strlen(user->password)) == 0))
{
strncpy(user->password,"ok",3);
send(newfd,user,sizeof(USER),0);
do_adminoperation(newfd,db);//跳转到管理员界面
}
else
{
strcpy(user->password,"yes");
send(newfd,user,sizeof(USER),0);
do_useroperation(newfd,db);//跳转到用户操作函数
}
return -1;
}
//密码或者用户名错误
if(nrow == 0)
{
strcpy(user->password,"user/password wrong");
send(newfd,user,sizeof(USER),0);
}
return 0;
}
int do_useroperation(int newfd,sqlite3 *db)//用户权限
{
INFO info;
char *acc;
while(recv(newfd,&info,sizeof(INFO),0) > 0 )
{
printf("user:request type:%d\n",info.cmd);
switch(info.cmd)
{
case S:
do_search(newfd,db,&info,acc);
memset(&info,0,sizeof(info));
break;
default:
printf("error\n");
break;
}
}
}
int do_adminoperation(int newfd,sqlite3 *db) //管理员登陆后操作
{
/*
函数功能:用来接受远程主机通过套接字sockfd发送来
的数据,并把这些数据保存在buf中
*/
char *acc;
INFO info;
while(recv(newfd,&info,sizeof(INFO),0) > 0 )
{
printf("user:request type:%d\n",info.cmd);
switch(info.cmd)
{
case A:
do_add(newfd,db,&info,acc);//添加信息
break;
case D:
do_del(newfd,db,&info,acc);//删除信息
break;
小项目员工管理系统的源代码
需积分: 8 200 浏览量
2023-02-28
23:00:15
上传
评论 1
收藏 6KB 7Z 举报
MisakaMikotto
- 粉丝: 62
- 资源: 2
最新资源
- Pytorch-pytorch深度学习教程之深度残差网络.zip
- Pytorch-pytorch深度学习教程之循环神经网络.zip
- Pytorch-pytorch深度学习教程之逻辑回归.zip
- Pytorch-pytorch深度学习教程之双向循环网络.zip
- Pytorch-pytorch深度学习教程之卷积神经网络.zip
- Pytorch-pytorch深度学习教程之前馈神经网络.zip
- Pytorch-pytorch深度学习教程之线性回归.zip
- Pytorch-pytorch深度学习教程之基本操作.zip
- 基于QT的地图可视化桌面系统后台数据库为MySQL5.7源码.zip
- 基于simulink的PLL锁相环系统仿真【包括模型,文档,参考文献,操作步骤】
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈