项目原理
采用多进程的方式实现多并发服务器
利用socket实现服务器和客户端之间的交互
利用sqlite3数据库来存储数据
实现过程
用户登录选择管理员模式和普通员工模式
管理员选择操作添加员工,删除员工,修改员工信息,查看历史记录
普通员工选择查询自己的信息,修改自己权限范围内的信息
效果:
登陆界面:
管理员登陆
添加员工
查找员工(工号查找)
删除员工
修改员工信息
打印历史信息
普通员工查询信息
普通员工修改信息
部分源码:
多进程服务器
void handler(int sig)
{
while(waitpid(-1,NULL,WNOHANG)>0);
}
int main(int argc, const char *argv[])
{
sighandler_t s = signal(SIGCHLD,handler);
if(SIG_ERR==s)
{
ERR_MSG("signal");
return -1;
}
//创建并打开一个数据库
if(sqlite3_open(STAFF_DATABASH,&db)!=SQLITE_OK)
{
ERR_MSG("sqlite3_open");
return -1;
}
//创建套接字
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd < 0)
{
ERR_MSG("socket");
return -1;
}
//允许端口快速重用
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
{
ERR_MSG("setsockopt");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
{
ERR_MSG("bing");
return -1;
}
//将套接字设置为被动监听状态
if(listen(sfd,10)<0)
{
ERR_MSG("listen");
return -1;
}
struct sockaddr_in cin;
socklen_t addrlen = sizeof(cin);
MSG msg;
int newfd;
pid_t pid;
while(1)
{
newfd = accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd < 0)
{
ERR_MSG("accept");
return -1;
}
printf("%s:%d newfd=%d accept\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
//创建一个子进程,与客户端进行交互
pid=fork();
if(0==pid)
{
close(sfd);
//交互
ssize_t res = 0;
while(1)
{
bzero(&msg,sizeof(MSG));
res = recv(newfd,&msg,sizeof(MSG),0);
if(res<0)
{
ERR_MSG("recv");
return -1;
}
tohandler(newfd,&msg);
}
close(newfd);
exit(0);
}
else if(pid>0)
{
close(newfd);
}
else
{
ERR_MSG("fork");
return -1;
}
}
close(sfd);
if(sqlite3_close(db)!=SQLITE_OK)
{
ERR_MSG("sqlite3_close");
return -1;
}
printf("sqlite3 close success\n");
return 0;
}