服务器头文件
#ifndef __HEAD_H__
#define __HEAD_H__
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <strings.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sqlite3.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sqlite3.h>
#define ERR_MSG(msg) do{\
fprintf(stdin,"line : %d",__LINE__);\
perror(msg);\
}while(0)
#define NAMELEN 30
#define DATALEN 128
#define PORT 8888
#define IP "192.168.1.250"
/*员工基本信息*/
typedef struct staff_info{
int no; //员工编号
int usertype; //ADMIN 0USER 1,类型
char name[NAMELEN];//姓名
char passwd[8]; //密码
int age; // 年龄
char phone[NAMELEN];//电话
char addr[DATALEN]; // 地址
char work[DATALEN]; //职位
char date[DATALEN];//入职年月
int level;// 等级,普通用户等级0,root用户等级1
double salary ;// 工资
}staff_info_t;
//usertype: 0:普通登录 1:普通用户查询 2:普通用户修改 3:root用户查询 4:root用户修改 5:root用户添加 6:root用户删除 7:root用户查询历史记录 8:退出
//9:root用户登录
/*定义双方通信的结构体信息*/
typedef struct {
int msgtype; //请求的消息类型
int usertype; //ADMIN 0USER 1
char username[NAMELEN]; //姓名
char passwd[8]; //登陆密码
char recvmsg[DATALEN]; //通信的消息
int flags; //标志位
void *released;
staff_info_t info; //员工信息
}MSG;
typedef struct{
int data;
char buf[600];
}send_data;
//创建tcp服务器
int create_tcp();
//创建用户数据库表格
sqlite3 *sqlite3_usr();
//创建历史记录表格
sqlite3 *sqlite_history();
//处理连接过来的客户端
int deal_cli();
//接收用户传递过来的信息,并且分辨
int deal_cli_msg(int newfd, struct sockaddr_in cin,sqlite3 *usrdb,sqlite3 *history_db);
//普通用户登录请求
int login_request(MSG *data,sqlite3 *usrdb,int newfd,sqlite3* history_db);
//root用户登录请求
int root_login_request(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//普通用户查询
int usr_query(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//普通用户修改
int usr_change(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//root用户查询
int root_query(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//root用户修改
int root_change(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//root用户添加
int root_add(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//root用户删除
int root_del(MSG *data,sqlite3 *usrdb,int newfd,sqlite3 *history_db);
//root用户查询历史记录
int root_history(MSG *data,sqlite3 *usrdb,int newfd);
//关闭数据库
int close_db(sqlite3 *db);
//回收僵尸进程
int signal_1();
//历史记录表格插入
int history_insert(char *msg,sqlite3* history);
#endif
服务器函数文件
#include "head.h"
MSG data_;
#define dataline sizeof(data_)
// 创建tcp服务器
int create_tcp()
{
// ipv4
// 字节流式套接字,流式套接字 ---》TCP
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if (sfd == -1)
{
ERR_MSG("socket create error");
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; // 必须填AF_INET;
sin.sin_port = htons(PORT); // 网络字节序的端口号1024~49151
sin.sin_addr.s_addr = inet_addr(IP); // 网络字节序的IP地址
// 将服务器的IP和端口绑定到套接字上,必须绑定
if (bind(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
// 将套接字设为被动监听状态
// socker 套接字,最大监听文件描述符个数
if (listen(sfd, 10) < 0)
{
ERR_MSG("listen");
return -1;
}
printf("tcp 服务器创建成功\n");
return sfd;
}
// 创建用户数据库表格
sqlite3 *sqlite3_usr()
{
// 打开数据库,如果数据库不存在,则创建并打开
sqlite3 *db = NULL;
if (sqlite3_open("./usr.db", &db) != SQLITE_OK)
{
ERR_MSG("sqlite3");
return NULL;
}
printf("数据库打开成功\n");
char sql[256] = "create table if not exists usr (no int PRIMARY KEY,name char,passwd char,age int ,phone char,addr char,work char,date char,level int ,salary double);";
char *errmsg = NULL;
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return NULL;
}
printf("创建usr表格成功\n");
return db;
}
// 创建历史记录表格
sqlite3 *sqlite_history()
{
// 打开数据库,如果数据库不存在,则创建并打开
sqlite3 *db = NULL;
if (sqlite3_open("./history.db", &db) != SQLITE_OK)
{
ERR_MSG("sqlite3");
return NULL;
}
printf("历史记录数据库成功\n");
char sql[256] = "create table if not exists history (no int,thing char,time char);";
char *errmsg = NULL;
if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return NULL;
}
printf("创建历史记录表格成功\n");
return db;
}
// 处理连接过来的客户端
int deal_cli(int sfd, struct sockaddr_in *cin, sqlite3 *history_db)
{
int newfd;
struct sockaddr_in qin;
socklen_t addrlen = sizeof(qin);
// 获取完成连接的客户端信息,并生成一个新的文件描述符
newfd = accept(sfd, (struct sockaddr *)&cin, &addrlen);
if (newfd < 0)
{
ERR_MSG("accept");
return -1;
}
// printf("获取新的文件描述符成功newfd = %d\n", newfd);
return newfd;
}
// 接收用户传递过来的信息,并且分辨
int deal_cli_msg(int newfd, struct sockaddr_in cin, sqlite3 *usrdb, sqlite3 *history_db)
{
int res; // 接收recv返回值
MSG data; // 接收信息的结构体
int data_line = dataline; // 接收信息结构体大小
while (1)
{
res = recv(newfd, &data, data_line, 0); // 阻塞方式接收
if (res == -1)
{
ERR_MSG("recv");
return -1;
}
else if (res == 0)
{
// 对端关闭
printf("[%s:%d] 客户端已退出\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port));
return -1;
}
printf("接收成功,%d\n", data.msgtype);
while (1)
{
// printf("11111111111:%d\n",data.info.no);
// printf("开始分辨 %d\n", data.msgtype);
switch (data.msgtype)
{
case 0:
// 普通用户登录
// 数据信息结构体,数据库首地址,文件描述符
login_request(&data, usrdb, newfd,history_db);
break;
case 1:
// 普通用户查询
usr_query(&data, usrdb, newfd,history_db);
break;
case 2:
// 普通用户修改
usr_change(&data, usrdb, newfd,history_db);
break;
case 3:
// root用户查询
root_query(&data, usrdb, newfd,history_db);
break;
case 4:
// root用户修改
root_change(&data, usrdb, newfd,history_db);
break;
case 5:
// root用户添加
root_add(&data, usrdb, newfd,history_db);
break;
case 6:
// root用户删除
root_del(&data, usrdb, newfd,history_db);
break;
case 7:
// root用户查询历史记录
root_history(&data, history_db, newfd);
break;
case 9:
// root用户登录
root_login_request(&data, usrdb, newfd,history_db);
break;
}
res = recv(newfd, &data, data_line, 0); // 阻塞方式接收
}
}
return 1;
}
// 普通用户登录请求
int login_request(MSG *data, sqlite3 *usrdb, int newfd, sqlite3 *history_db)
{
char *errmsg = NULL;
char **pres = NULL;
int row, column;
int i; // for循环变量
char buf[300];
strcpy(buf, "select no,name,passwd from usr;");
if (sqlite3_get_table(usrdb, buf, &pres, &row, &column, &errmsg) != SQLITE_OK)
{
ERR_MSG("sqlite3 get table");
return -1;
}
recv(newfd, data, dataline, 0);
// printf("****%s:%s\n",data->info.name,data->info.passwd);
int flag = 0;
for (i = 0; i < (row + 1) * column; i++)
{
if (strcmp(data->info.name, pres[i]) == 0 && strcmp(data->info.passwd, pres[i + 1]) == 0)
{
// 登录成功
// printf("登录成功\n");
strcpy(data->recvmsg, "登录成功");
data->info.no = atoi(pres[3]);
// printf("---%d\n", data->info.no);
send(newfd, data, dataline, 0);
flag = 1;
break;
}
// printf("%d***%s\n",i,pres[i]);
}
if (flag = 0)
{
// printf("用户名或密码错误\n");
strcpy(data->recvmsg, "用户名或密码错误");
send(newfd, data, dataline, 0);
return -1;
}
bzero(buf, sizeof(buf));
time_t t2;
time(&t2);
struct tm *info = NULL;
info = localtime(&t2);
sprintf(buf,"%d-%02d-%02d %02d-%02d-%02d",info->tm_year+1900, info->tm_mon+1, info->tm_mday, \
info->tm_hour, info->tm_min, info->tm_sec);
send_data data_send;
sprintf(data_send.buf, "INSERT INTO history VALUES (%d, '普通用户登录成功', '%s');", data->info.no, buf);
if (sqlite3_exec(history_db, data_send.buf, NULL, NULL, &errmsg) != SQLITE_OK)
{
fprintf(stderr, "line:%d sqlite3_exec:%s\n", __LINE__, errmsg);
return -1;
}
return 0;
}
// root用户登录请求
int root_login_request(MSG *data, sqlite3 *usrdb, int newfd,sqlite3 *history_db)
{
char *errmsg = NULL;
char **pres = NULL;
int row, column;
int i; // for循环变量
char buf[300];
strcp