目录
- 要求
-
- 该客户端Shell的图形界面(很简单只是一个 ` 选择 `)
-
要求
- 服务端支持客户端远程登录TCP
- 支持多用户同时访问( 服务器并发 多进程 )
- 服务端管理所有员工数据信息(用户分级管理<管理员、普通用户>)
- 管理员可以对所有员工的数据信息进行增、删、改、查
- 普通用户只可以查询自身信息数据 且 可以修改除薪资和职务以外的数据
- 数据管理 sqlite3
代码
服务器
server.c
#include "./server.h"
int main(int argc, char const *argv[])
{
sqlite3 *sql_db=proc_init();
if (3 != argc)
{
printf("Usage : %s \n", argv[0]);
exit(-1);
}
int sockfd = socket_bind_listen(argv);
struct sockaddr_in client_addr;
memset(&client_addr, 0, sizeof(client_addr));
socklen_t client_addr_len = sizeof(client_addr);
pid_t pid;
int accept_fd;
while (1)
{
accept_fd=accept(sockfd,(struct sockaddr *)&client_addr, &client_addr_len);
if (-1==accept_fd) ERRLOG("accept error");
printf("客户端[%s : %d]连接\n",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
if (0>(pid=fork())) ERRLOG("fork error");
else if (0==pid)
{
child_do(accept_fd,sql_db);
}
else
{
if (signal(SIGCHLD, deal_signal) == SIG_ERR)
ERRLOG("signal error");
close(accept_fd);
}
}
close(sockfd);
return 0;
}
sqlite3 *proc_init(void)
{
sqlite3 *sql_db=NULL;
int ret=sqlite3_open(FILEname,&sql_db);
if (ret!=SQLITE_OK)
{
printf("打开数据库文件 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
char sql_rbuf[256]="CREATE TABLE IF NOT EXISTS root(id INT PRIMARY KEY, pass TEXT)";
ret=sqlite3_exec(sql_db,sql_rbuf,NULL,NULL,NULL);
if (ret!=SQLITE_OK)
{
perror("建root表 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
char sql_ubuf[256]="CREATE TABLE IF NOT EXISTS user(id INT PRIMARY KEY,pass TEXT,name TEXT,sex TEXT,age INT,pay INT,job TEXT)";
ret=sqlite3_exec(sql_db,sql_ubuf,NULL,NULL,NULL);
if (ret!=SQLITE_OK)
{
perror("建user表 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
return sql_db;
}
int socket_bind_listen(const char *argv[])
{
int sockfd=socket(AF_INET,SOCK_STREAM,0);
if (-1==sockfd) ERRLOG("创建套接字 失败");
struct sockaddr_in server_addr;
memset(&server_addr,0,sizeof(server_addr));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(atoi(argv[2]));
server_addr.sin_addr.s_addr=inet_addr(argv[1]);
socklen_t server_addr_len=sizeof(server_addr);
if (-1==bind(sockfd,(struct sockaddr *)&server_addr,server_addr_len))
ERRLOG("结构体绑定 失败");
if (-1 == listen(sockfd, 10))
ERRLOG("listen error");
return sockfd;
}
void child_do(int accept_fd, sqlite3 *sql_db)
{
MSG msg;
memset(&msg,0,sizeof(MSG));
while (recv(accept_fd, &msg, sizeof(MSG), 0) > 0)
{
printf("type = %d\n", msg.type);
switch (msg.type)
{
case R:
do_register_s(accept_fd, &msg, sql_db);
break;
case L:
do_login_s(accept_fd, &msg, sql_db);
break;
case Q:
do_query_s(accept_fd, &msg, sql_db);
break;
case M:
do_Modify_s(accept_fd, &msg, sql_db);
break;
case ROOT:
root_login_s(accept_fd, &msg, sql_db);
break;
case D:
root_delete_s(accept_fd, &msg, sql_db);
break;
case Qall:
all_query_s(accept_fd,sql_db);
break;
}
}
printf("客户端 退出\n");
exit(0);
}
void deal_signal(int s)
{
wait(NULL);
}
void do_register_s(int accept_fd, MSG *msg, sqlite3 *sql_db)
{
char sql_buf[512];
memset(sql_buf,0,sizeof(sql_buf));
sprintf(sql_buf,"INSERT INTO user(id,pass) VALUES(%d,'%s')", msg->id, msg->pass);
int ret=sqlite3_exec(sql_db,sql_buf,NULL,NULL,NULL);
if (ret!=SQLITE_OK)
{
perror("注册 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
sprintf(msg->data, "ID %d 已经存在!!!", msg->id);
}
else
{
strcpy(msg->data, "注册成功");
}
if (0 >= send(accept_fd,msg, sizeof(MSG), 0))
ERRLOG("send error");
}
void do_login_s(int accept_fd, MSG *msg, sqlite3 *sql_db)
{
char sql_buf[256]={0};
sprintf(sql_buf,"SELECT * FROM user WHERE id=%d AND pass='%s'", msg->id, msg->pass);
char **result;
int row = 0;
int column = 0;
int ret=sqlite3_get_table(sql_db,sql_buf,&result,&row,&column,NULL);
if (ret!=SQLITE_OK)
{
perror("查询 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
if (0==row)
{
sprintf(msg->data,"ID[%d]与密码[%s]不一致", msg->id,msg->pass);
}
else
{
strcpy(msg->data, "登录成功");
}
if (0 >= send(accept_fd, msg, sizeof(MSG), 0))
ERRLOG("send error");
}
void do_query_s(int accept_fd, MSG *msg, sqlite3 *sql_db)
{
int id=msg->id;
memset(msg,0,sizeof(MSG));
msg->id=id;
char sql_buf[256]={0};
sprintf(sql_buf,"SELECT * FROM user WHERE id=%d",msg->id);
char **result={0};
int row = 0;
int column = 0;
int ret=sqlite3_get_table(sql_db,sql_buf,&result,&row,&column,NULL);
if (ret!=SQLITE_OK)
{
perror("查询 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
if (0==row)
{
sprintf(msg->data,"ID[%d]为空", msg->id);
}
else
{
if (result[column])
{
msg->id=atoi(result[column]);
}
snprintf(msg->pass,sizeof(msg->pass),"%s",result[column+1]);
snprintf(msg->name,sizeof(msg->name),"%s",result[column+2]);
snprintf(msg->sex,sizeof(msg->sex),"%s",result[column+3]);
if (result[column+4])
{
msg->age=atoi(result[column+4]);
}
if (result[column+5])
{
msg->pay=atoi(result[column+5]);
}
snprintf(msg->job,sizeof(msg->job),"%s",result[column+6]);
}
if (0 >= send(accept_fd,msg, sizeof(MSG), 0))
ERRLOG("send error");
sqlite3_free_table(result);
}
void do_Modify_s(int accept_fd, MSG *msg, sqlite3 *sql_db)
{
char sql_buff[512] = {0};
sprintf(sql_buff,"UPDATE user SET pass='%s',name='%s',sex='%s',age=%d,pay=%d,job='%s' WHERE id=%d",
msg->pass,msg->name,msg->sex,msg->age,msg->pay,msg->job,msg->id);
int ret = sqlite3_exec(sql_db, sql_buff, NULL, NULL, NULL);
if (ret != SQLITE_OK)
{
perror("修改 失败");
printf("返回值[%d] 错误信息[%s]\n", ret, sqlite3_errmsg(sql_db));
exit(-1);
}
strcpy(msg->data, "修改成功");
if (0 >= send(accept_fd,msg, sizeof(MSG), 0))
ERRLOG("send error");
memset(msg,0,sizeof(MSG));
}
void root_login_s(int accept_fd, MSG *msg, sqlite3 *sql_db)
{
char sql_buf[256]={0};
sprintf(sql_buf,"SELECT * FROM root WHERE id=%d AND pass='%s'",123456, msg->pass);
char **result;
int row = 0;
int column = 0;
int ret=sqlite3_get_table(sql_db,sql_buf,&result,&row,&column,NULL);
if (ret!=SQLITE_OK)
{
perror("查询 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
if (0==row)
{
sprintf(msg->data,"ID[%d]与密码[%s]不一致", msg->id,msg->pass);
}
else
{
strcpy(msg->data, "登录成功");
}
if (0 >= send(accept_fd, msg, sizeof(MSG), 0))
ERRLOG("send error");
memset(msg,0,sizeof(MSG));
}
void root_delete_s(int accept_fd, MSG *msg, sqlite3 *sql_db)
{
char sql_buf[256]={0};
sprintf(sql_buf,"DELETE FROM user WHERE id=%d",msg->id);
int ret = sqlite3_exec(sql_db, sql_buf, NULL, NULL, NULL);
if (ret!=SQLITE_OK)
{
perror("查询 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
else
{
strcpy(msg->data, "删除成功");
}
if (0 >= send(accept_fd, msg, sizeof(MSG), 0))
ERRLOG("send error");
memset(msg,0,sizeof(MSG));
}
void all_query_s(int accept_fd,sqlite3 *sql_db)
{
MSG msg;
int i,x;
char sql_buf[256]={0};
memset(&msg,0,sizeof(msg));
strcpy(sql_buf,"SELECT * FROM user");
char **result;
int row = 0;
int column = 0;
int ret=sqlite3_get_table(sql_db,sql_buf,&result,&row,&column,NULL);
if (ret!=SQLITE_OK)
{
perror("查询 失败");
printf("errcode[%d] errmsg[%s]\n", ret, sqlite3_errmsg(sql_db));
}
if (0==row)
{
sprintf(msg.data,"ID[%d]为空", 0);
}
else
{
x=column;
for (i= 0; i<row; i++)
{
if (result[x])
{
msg.id=atoi(result[x]);
}
x++;
snprintf(msg.pass,sizeof(msg.pass),"%s",result[x++]);
snprintf(msg.name,sizeof(msg.name),"%s",result[x++]);
snprintf(msg.sex,sizeof(msg.sex),"%s",result[x++]);
if (result[x])
{
msg.age=atoi(result[x]);
}
x++;
if (result[x])
{
msg.pay=atoi(result[x]);
}
x++;
snprintf(msg.job,sizeof(msg.job),"%s",result[x++]);
if (0 >= send(accept_fd,&msg, sizeof(MSG), 0))
ERRLOG("send error");
memset(&msg,0,sizeof(msg));
if (row==(i+1))
{
strcpy(msg.data,"**over**");
if (0 >= send(accept_fd,&msg, sizeof(MSG), 0))
ERRLOG("send error");
}
}
}
sqlite3_free_table(result);
}
server.h
#ifndef __SERVER_H__
#define __SERVER_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define FILEname "ser.db"
#define ERRLOG(errmsg) \
do \
{ \
printf("%s--%s(%d):", __FILE__, __func__, __LINE__); \
perror(errmsg); \
} while (0)
#define R 1
#define L 2
#define Q 3
#define M 4
#define ROOT 5
#define D 6
#define Qall 7
#define N 32
typedef struct
{
int type;
int id;
char name[N];
char pass[64];
char data[256];
char sex[32];
int age;
int pay;
char job[64];
}MSG;
sqlite3 *proc_init(void);
int socket_bind_listen(const char *argv[]);
void child_do(int accept_fd, sqlite3 *sql_db);
void deal_signal(int s);
void do_register_s(int accept_fd, MSG *msg, sqlite3 *sql_db);
void do_login_s(int accept_fd, MSG *msg, sqlite3 *sql_db);
void do_query_s(int accept_fd, MSG *msg, sqlite3 *sql_db);
void do_Modify_s(int accept_fd, MSG *msg, sqlite3 *sql_db);
void root_login_s(int accept_fd, MSG *msg, sqlite3 *sql_db);
void root_delete_s(int accept_fd, MSG *msg, sqlite3 *sql_db);
void all_query_s(int accept_fd,sqlite3 *sql_db);
#endif
客户端
client.c
#include "./client.h"
int errnum=0;
int root = 0,root2= 0;
int main(int argc, char const *argv[])
{
int ret;
if (3 != argc)
{
printf("Usage : %s \n", argv[0]);
exit(-1);
}
int sockfd = socket_connect(argv);
MSG msg;
memset(&msg, 0, sizeof(MSG));
int n;
while (1)
{
printf("************************************\n");
printf("* 1: 登录 2: 退出 *\n");
printf("************************************\n");
printf("please choose : ");
if (scanf("%d", &n) <= 0)
{
perror("scanf");
exit(-1);
}
switch (n)
{
case 1:
if (do_login(sockfd, &msg) == 1)
goto next;
break;
case 2:
close(sockfd);
break;
}
}
next:
while (1)
{
if (0 == root)
{
printf("************************************\n");
printf("* 1: 查询 2: 修改 3: 退出 *\n");
printf("************************************\n");
printf("please choose : ");
if (scanf("%d", &n) <= 0)
{
perror("scanf");
exit(-1);
}
switch (n)
{
case 1:
do_query(sockfd, &msg);
break;
case 2:
do_Modify(sockfd, &msg);
break;
case 3:
close(sockfd);
exit(0);
}
}
if (1 == root)
{
printf("********************************************************\n");
printf("* 1: 注册(增) 2: 删除 3: 修改 4: 查询 5: 退出 *\n");
printf("********************************************************\n");
printf("please choose : ");
if (scanf("%d", &n) <= 0)
{
perror("scanf");
exit(-1);
}
switch (n)
{
case 1:
do_register(sockfd, &msg);
break;
case 2:
do_delete(sockfd, &msg);
break;
case 3:
do_Modify(sockfd, &msg);
break;
case 4:
do_query(sockfd, &msg);
break;
case 5:
root=0;
close(sockfd);
exit(0);
}
}
}
close(sockfd);
return 0;
}
int socket_connect(const char *argv[])
{
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (-1 == sockfd)
ERRLOG("创建套接字 失败");
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(atoi(argv[2]));
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
socklen_t server_addr_len = sizeof(server_addr);
if (-1 == connect(sockfd, (struct sockaddr *)&server_addr, server_addr_len))
{
ERRLOG("listen error");
exit(-1);
}
printf("---连接服务器成功---\n");
return sockfd;
}
void do_register(int sockfd, MSG *msg)
{
memset(msg, 0, sizeof(MSG));
msg->type = R;
printf("输入ID: ");
scanf("%d", &msg->id);
printf("输入[%d] 密码: ", msg->id);
scanf("%s", msg->pass);
if (0 >= send(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error");
if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error");
printf("%s\n", msg->data);
}
int do_login(int sockfd, MSG *msg)
{
char NO[32] = "n";
char unlogin[128]={0};
printf("是否管理员(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
msg->type = ROOT;
root = 1;
printf("输入 [%d] 密码: ", msg->id);
scanf("%s", msg->pass);
goto root;
}
msg->type = L;
root = 0;
printf("输入ID: ");
scanf("%d", &msg->id);
printf("输入 [%d] 密码: ", msg->id);
scanf("%s", msg->pass);
root:
if (0 >= send(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error ?");
if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
ERRLOG("recv error");
printf("%s\n", msg->data);
sprintf(unlogin,"ID[%d]与密码[%s]不一致", msg->id,msg->pass);
if (strcmp(msg->data,unlogin)== 0)
{
errnum++;
if (3==errnum)
{
errnum=0;
exit(0);
}
}
if (strcmp(msg->data, "登录成功") == 0)
{
if (1==root)
{
memset(msg,0,sizeof(MSG));
}
return 1;
}
return 0;
}
int do_query(int sockfd, MSG *msg)
{
int id=msg->id;
memset(msg,0,sizeof(MSG));
msg->id=id;
char zoor[64]={0};
msg->type = Q;
if (1==root&&0==root2)
{
printf("输入查询ID{0 all}: ");
scanf("%d", &msg->id);
if (0==msg->id)
{
goto ALLQ;
}
}
if (0 >= send(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error");
if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
ERRLOG("recv error");
sprintf(zoor,"ID[%d]为空", msg->id);
if (strcmp(msg->data, zoor) == 0)
{
printf("%s\n", msg->data);
}
else{
printf("id |pass |name |sex |age |pay |job |\n");
printf("%d\t%s\t%s\t%s\t%d\t%d\t%s\n", msg->id, msg->pass, msg->name, msg->sex, msg->age, msg->pay, msg->job);
errnum++;
if (3==errnum)
{
errnum=0;
printf("休息一下,您已经输错3次\n");
exit(0);
}
}
return 0;
ALLQ:
All_query(sockfd, msg);
}
void do_Modify(int sockfd, MSG *msg)
{
root2=1;
if (1==root)
{
printf("输入修改ID: ");
scanf("%d", &msg->id);
}
do_query(sockfd,msg);
char NO[32] = "n";
int flag=0;
msg->type = M;
printf("开始修改ID: [%d] 信息\n", msg->id);
printf("修改密码(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
memset(msg->pass, 0, sizeof(msg->pass));
printf("新密码: ");
scanf("%s", msg->pass);
flag=1;
}
printf("修改名字(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
memset(msg->name, 0, sizeof(msg->name));
printf("新名字: ");
scanf("%s", msg->name);
flag=1;
}
printf("修改性别(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
memset(msg->sex, 0, sizeof(msg->sex));
printf("新性别: ");
scanf("%s", msg->sex);
flag=1;
}
printf("修改年龄(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
printf("新年龄: ");
scanf("%d", &msg->age);
flag=1;
}
if (1==root)
{
printf("修改工资(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
printf("新工资: ");
scanf("%d", &msg->pay);
flag=1;
}
printf("修改职位(y/n): ");
scanf("%s", NO);
if (strcmp(NO, "y") == 0 || strcmp(NO, "Y") == 0)
{
printf("新职位: ");
scanf("%s", msg->job);
flag=1;
}
}
if (0==flag)
{
printf("无更新\n");
}
else
{
if (0 >= send(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error");
if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
ERRLOG("recv error");
if (strcmp(msg->data, "修改成功") == 0)
{
printf("%s\n", msg->data);
}
}
root2=0;
}
void do_delete(int sockfd, MSG *msg)
{
printf("输入删除ID: ");
scanf("%d", &msg->id);
msg->type = D;
if (0 >= send(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error");
if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
ERRLOG("recv error");
printf("%s\n", msg->data);
}
void All_query(int sockfd, MSG *msg)
{
memset(msg, 0, sizeof(MSG));
int flag=0;
char zoor[64]={0};
sprintf(zoor,"ID[%d]为空", 0);
msg->type = Qall;
if (0 >= send(sockfd, msg, sizeof(MSG), 0))
ERRLOG("send error");
while (1)
{
if (0 >= recv(sockfd, msg, sizeof(MSG), 0))
ERRLOG("recv error");
if (strcmp(msg->data, zoor) == 0)
{
printf("%s\n", msg->data);
}
if (strcmp(msg->data,"**over**") == 0)
{
printf("输出成功\n");
break;
}
else
{
if (0==flag)
{
printf("id |pass |name |sex |age |pay |job |\n");
flag=1;
}
printf("%d\t%s\t%s\t%s\t%d\t%d\t%s\n", msg->id, msg->pass, msg->name, msg->sex, msg->age, msg->pay, msg->job);
memset(msg, 0, sizeof(MSG));
}
}
flag=0;
}
client.h
#ifndef __SERVER_H__
#define __SERVER_H__
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ERRLOG(errmsg) \
do \
{ \
printf("%s--%s(%d):", __FILE__, __func__, __LINE__); \
perror(errmsg); \
} while (0)
#define R 1
#define L 2
#define Q 3
#define M 4
#define ROOT 5
#define D 6
#define Qall 7
#define N 32
typedef struct
{
int type;
int id;
char name[N];
char pass[64];
char data[256];
char sex[32];
int age;
int pay;
char job[64];
}MSG;
int socket_connect(const char *argv[]);
void do_register(int sockfd,MSG *msg);
int do_login(int sockfd, MSG *msg);
int do_query(int sockfd, MSG *msg);
void do_Modify(int sockfd, MSG *msg);
void do_delete(int sockfd, MSG *msg);
void All_query(int sockfd, MSG *msg);
#endif
执行结果
该客户端Shell的图形界面(很简单只是一个 选择
)
sudo apt-get install dialog
menu.sh
#!/bin/bash
# simple script menu
function Performing {
clear
cd /home/linux/xxxxxxxxx目录(pwd)查看xxxxxxxxx/03epoll员工/客户端
dialog --title "Questionnaire" --inputbox "请输入端口号 " 9 30 2>_1.txt
port=$(cat _1.txt)
./cli 127.0.0.1 $port
}
function menu {
clear
# 重定向标准错误输出流(2)到“_1.txt”。
dialog --menu " 员工管理系统 " 15 30 2 1 "进入" 0 "退出" 2>_1.txt
if [ $? -ne 0 ]; then # yes的返回码为0,“$?”为上一个命令的退出状态。
dialog --clear # “-clear”作用为清屏。
clear
exit 0
fi
option=$(cat _1.txt)
}
while [ 1 ]; do
menu
case $option in
0)
break
;;
1)
Performing
;;
*)
clear
echo "对不起,错误的选择"
;;
esac
done
clear
- bash menu.sh
- 输入端口号
- 本质就是
./cli 127.0.0.1 8888