员工管理系统

这篇博客详细介绍了如何构建一个员工管理系统,涉及到服务器和客户端的实现。内容包括服务器的头文件、函数文件和主程序,以及客户端的头文件、函数文件和主程序的编写,展示了网络编程在系统管理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

服务器头文件

#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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值