员工管理系统项目(C语言)

一、项目说明:

        开发环境:Linux

        开发语言:C语言

二、项目描述:本项目是基于TCP的,多进程实现并发服务器支持多客户端的访问。实现用户注册登录,查询信息,修改信息,管理员注册登录,增加,删除,修改,查询员工信息等。以下是代码,分为客户端和服务器端,只供参考。

服务器端:

#include <head.h>//自己定义的头文件,可以自己添加
#include <sqlite3.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#define R 1 //用户注册
#define L 2 //用户登录
#define D 3 //删除
#define M 4 //修改
#define Q 5 //查询
#define N 512
typedef struct MSG
{
    int type;         // 1为管理员,2为普通用户
    int type2;        //用户选项
    char name[16];    //管理员名字
    char pd[128]; //密码或数据
    int age;
    int salary;
    char data[N];
    char data2[N];
    char office[64];
    int flag;
} msg_t;
int flag = 0; //控制打印表头的标志位  0 要打印  1 不打印
void do_client1(int, sqlite3 *, msg_t *);
int do_register(int acceptfd, msg_t *, sqlite3 *);
int do_login(int, msg_t *, sqlite3 *);
void do_delete(int, msg_t *, sqlite3 *);
void do_modify(int, msg_t *, sqlite3 *);
void do_query(int, msg_t *, sqlite3 *);
int callback(void *, int, char **, char **);
void handler()
{
    wait(NULL);
}

int main(int argc, const char *argv[])
{
    int sockfd;
    if (argc != 3)
    {
        printf("Usage: %s <ip> <port>\n", argv[0]);
        exit(-1);
    }
    //创建套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd)
    {
        PRINT_ERR("socket error");
    }
    //打开数据库
    sqlite3 *db = NULL;
    char *errmsg;
    int ret = sqlite3_open("my.db", &db);
    if (ret != SQLITE_OK)
    {
        PRINT_ERR("open error");
    }
    char buff[N] = {0};
    sprintf(buff, "%s", "CREATE TABLE IF NOT EXISTS admin(aname TEXT PRIMARY KEY,pd TEXT)");
    if (SQLITE_OK != (ret = sqlite3_exec(db, buff, NULL, NULL, &errmsg)))
    {
        printf("%s(%d): errcode:[%d] errmsg:[%s]\n", __FILE__, __LINE__, ret, errmsg);
        exit(-1);
    }
    char buff1[N] = {0};
    sprintf(buff1, "%s", "CREATE TABLE IF NOT EXISTS employee(uname TEXT PRIMARY KEY,pd TEXT,age INT,salary INT,office TEXT)");
    if (SQLITE_OK != (ret = sqlite3_exec(db, buff1, NULL, NULL, &errmsg)))
    {
        printf("%s(%d): errcode:[%d] errmsg:[%s]\n", __FILE__, __LINE__, ret, errmsg);
        exit(-1);
    }

    //创建服务器网络信息结构体
    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = inet_addr(argv[1]);
    server_addr.sin_port = htons(atoi(argv[2]));
    socklen_t addrlen = sizeof(server_addr);

    //绑定套接字和网络信息结构体
    if (-1 == bind(sockfd, (struct sockaddr *)&server_addr, addrlen))
    {
        PRINT_ERR("bind error");
    }

    //设置为被动监听状态
    if (-1 == listen(sockfd, 100))
    {
        PRINT_ERR("listen error");
    }

    //读写数据
    //处理僵尸进程
    signal(SIGCHLD, handler);
    pid_t pid;
    msg_t msg;
    //使用多进程实现并发服务器
    while (1)
    {
        //阻塞等待客户端连接
        int acceptfd = accept(sockfd, NULL, NULL);
        if (-1 == acceptfd)
        {
            PRINT_ERR("accept error");
        }
        pid = fork();
        if (pid < 0)
        {
            PRINT_ERR("fork error");
        }
        else if (pid == 0)
        {
            //子进程
            recv(acceptfd, &msg, sizeof(msg_t), 0);

            do_client1(acceptfd, db, &msg);
        }
        else
        {
            //父进程
            close(acceptfd);
        }
    }

    sqlite3_free(errmsg);
    return 0;
}

void do_client1(int acceptfd, sqlite3 *db, msg_t *msg) //管理员
{
    int n = 0;
AGAIN:
    while (recv(acceptfd, msg, sizeof(msg_t), 0) > 0)
    {
        if (msg->type == 1)
        { //管理员

            switch (msg->type2)
            {
            case R: //注册

                if (0 != do_register(acceptfd, msg, db))
                { //注册失败
                    printf("注册管理员:%s失败\n", msg->name);
                }
                goto AGAIN;
                break;
            case L:                                   //登录
                if (do_login(acceptfd, msg, db) == 0) //登录成功
                {
                    printf("进入管理员界面了\n");
                    goto AGAIN;
                }
                else
                {
                    printf("管理员登录失败\n");
                    n++;
                    if (n == 2)
                    {
                        printf("%s退出了\n", msg->name);
                        exit(0);
                    }
                    goto AGAIN;
                }
                break;
            case D: //删除
                do_delete(acceptfd, msg, db);
                break;
            case M: //修改
                do_modify(acceptfd, msg, db);
                break;
            case Q: //查询
                do_query(acceptfd, msg, db);
                break;
            }
        }
        else if (msg->type == 2)
        { //普通用户

            switch (msg->type2)
            {
            case R: //注册
                if (0 != do_register(acceptfd, msg, db))
                { //注册失败
                    printf("注册用户:%s失败\n", msg->name);
                }
                goto AGAIN;
                break;
            case L: //登录
                if (0 == do_login(acceptfd, msg, db))
                {
                    printf("进入用户界面了\n");
                    goto AGAIN;
                }
                else
                {
                    printf("用户登录失败\n");
                    n++;
                    if (n == 2)
                    {
                        printf("%s退出了\n", msg->name);
                        exit(0);
                    }
                    goto AGAIN;
                }
                break;
            case M: //修改,只能修改除薪资和职务以外的数据
                do_modify(acceptfd, msg, db);
                break;
            case Q: //普通用户只能查询自己的信息
                do_query(acceptfd, msg, db);
                break;
            }
        }
        memset(msg, 0, sizeof(msg_t));
    }
    printf("%s退出了\n", msg->name);
    exit(0);
}

//注册
int do_register(int acceptfd, msg_t *msg, sqlite3 *db)
{
    char buff[512] = {0};
    char *errmsg = NULL;

    //使用sqlite3_exec函数判断是否能插入成功
    //由于用户名设置为主键,所以如果用户名已经存在就会报错
    if (msg->type == 1) //管理员
    {
        sprintf(buff, "INSERT INTO admin values('%s','%s')", msg->name, msg->pd);
        if (sqlite3_exec(db, buff, NULL, NULL, &errmsg) != SQLITE_OK)
        {
            sprintf(msg->data, "管理员 %s 已存在!!!", msg->name);

            send(acceptfd, msg, sizeof(msg_t), 0);
            return -1;
        }
        else
        {
            strcpy(msg->data, "注册管理员成功");
            printf("注册管理员:%s成功\n", msg->name);
            send(acceptfd, msg, sizeof(msg_t), 0);
            return 0;
        }
    }
    else if (msg->type == 2) //普通用户
    {
        sprintf(buff, "INSERT INTO employee values('%s','%s','%d','%d','%s')", msg->name, msg->passwd, msg->age, msg->salary, msg->office);
        if (sqlite3_exec(db, buff, NULL, NULL, &errmsg) != SQLITE_OK)
        {
            sprintf(msg->data, "用户 %s 已存在!!!", msg->name);
            printf("注册用户:%s失败\n", msg->name);
            send(acceptfd, msg, sizeof(msg_t), 0);
            return -1;
        }
        else
        {
            strcpy(msg->data, "注册用户成功");
            printf("注册用户:%s成功\n", msg->name);
            send(acceptfd, msg, sizeof(msg_t), 0);
            return 0;
        }
    }
}
//登录
int do_login(int acceptfd, msg_t *msg, sqlite3 *db)
{
    char sqlstr[512] = {0};
    char *errmsg, **result;
    int nrow, ncolum;

    //通过sqlite3_get_table函数查询记录是否存在
    if (msg->type == 1)
    {
        sprintf(sqlstr, "select * from admin where aname = '%s' and pd = '%s'", msg->name, msg->passwd);
    }
    else if (msg->type == 2)
    {
        sprintf(sqlstr, "select * from employee where uname = '%s' and pd = '%s'", msg->name, msg->passwd);
    }
    if (sqlite3_get_table(db, sqlstr, &result, &nrow, &ncolum, &errmsg) != SQLITE_OK)
    {

        printf("登录失败error:%s\n", errmsg);
    }
    //通过nrow参数判断是否能够查询到记录,如果值为0,则查询不到,如果值为非0,则查询到
    if (nrow == 0)
    {
        strcpy(msg->data, "名字或密码错误!!!");
        send(acceptfd, msg, sizeof(msg_t), 0);
        return -1;
    }
    else
    {
        strncpy(msg->data, "OK", 256);
        send(acceptfd, msg, sizeof(msg_t), 0);
        return 0;
    }
}

//删除,只有管理员
void do_delete(int acceptfd, msg_t *msg, sqlite3 *db)
{
    char buff[N] = {0};
    char *errmsg, **result;
    int nrow, ncolum;
    sprintf(buff, "select * from employee where uname = '%s'", msg->name);
    if (sqlite3_get_table(db, buff, &result, &nrow, &ncolum, &errmsg) != SQLITE_OK)
    {
        printf("遍历查询失败error: %s\n", errmsg);
    }
    if (nrow == 0)
    {
        strcpy(msg->data, "用户不存在");
    }
    memset(buff, 0, sizeof(buff));
    sprintf(buff, "DELETE FROM employee WHERE uname='%s'", msg->name);
    if (sqlite3_exec(db, buff, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        printf("删除失败error: %s\n", errmsg);
        strcpy(msg->data,"删除失败");
        
    }
    strcpy(msg->data, "删除成功");
    send(acceptfd, msg, sizeof(msg_t), 0);
    
    sqlite3_free(errmsg);
    sqlite3_free_table(result);
}

//修改,用户只能修改除薪资和职务以外的数据
void do_modify(int acceptfd, msg_t *msg, sqlite3 *db)
{
    char buff[N] = {0};
    char *errmsg;
    if (msg->type == 1) //管理员
    {
        sprintf(buff, "UPDATE employee SET salary='%d',office='%s' WHERE uname='%s'", msg->salary, msg->office, msg->name);
    }
    else if (msg->type == 2)
    { //普通用户
        sprintf(buff, "UPDATE employee SET age='%d',passwd='%s' WHERE uname='%s'", msg->age, msg->passwd, msg->name);
    }
    if (sqlite3_exec(db, buff, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        printf("修改失败error: %s\n", errmsg);
    }
    strcpy(msg->data, "修改成功");
    printf("修改成功\n");
    printf("%d %s\n",msg->age,msg->passwd);
    send(acceptfd, msg, sizeof(msg_t), 0);
    return;
}

//查询
void do_query(int acceptfd, msg_t *msg, sqlite3 *db)
{
    char buff[N] = {0};
    char *errmsg, **result;
    int nrow = 0;
    int ncolumn = 0;
    int i = 0;
    int j = 0;
    if (msg->type == 1)
    { //管理员
        sprintf(buff, "SELECT * FROM employee");
        if (sqlite3_get_table(db, buff, &result, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
        {
            printf("查询失败errmsg:%s\n", errmsg);
            strcpy(msg->data, "查询失败");
            send(acceptfd, msg, sizeof(msg_t), 0);
        }
        //输出表头
        sprintf(msg->data2, "%10s%10s%10s%10s%10s", result[0], result[1], result[2], result[3], result[4]);
        int index = 5;
        sprintf(msg->data2 + strlen(msg->data2), "\n");
        //输出各条记录各个字段的值
        for (i = 0; i < nrow; i++)
        { // i控制查到的记录数,行数,不包括表头行
            for (j = 0; j < ncolumn; j++)
            {
                sprintf(msg->data2 + strlen(msg->data2), "%10s", result[index++]);
            }
            sprintf(msg->data2 + strlen(msg->data2), "\n");
        }
        sprintf(msg->data2 + strlen(msg->data2), "\n");
        strcpy(msg->data, "查询成功");
        printf("查询成功\n");
        send(acceptfd, msg, sizeof(msg_t), 0);
    }else if(msg->type == 2){
        sprintf(buff, "SELECT * FROM employee WHERE uname='%s'",msg->name);
        if (sqlite3_get_table(db, buff, &result, &nrow, &ncolumn, &errmsg) != SQLITE_OK)
        {
            printf("查询失败errmsg:%s\n", errmsg);
            strcpy(msg->data, "查询失败");
            send(acceptfd, msg, sizeof(msg_t), 0);
        }
        int index = 0;
        for (i = 0; i < nrow+1; i++)
        { // i控制查到的记录数,行数,不包括表头行
            for (j = 0; j < ncolumn; j++)
            {
                sprintf(msg->data2 + strlen(msg->data2), "%10s", result[index++]);
            }
            sprintf(msg->data2 + strlen(msg->data2), "\n");
        }
        sprintf(msg->data2 + strlen(msg->data2), "\n");        
        strcpy(msg->data, "查询成功");
        printf("查询成功\n");
        send(acceptfd, msg, sizeof(msg_t), 0);
    }
    sqlite3_free_table(result);
    sqlite3_free(errmsg);
}

客户端:

#include <head.h>
#define R 1 //用户注册
#define L 2 //用户登录
#define D 3 //删除
#define M 4 //修改
#define Q 5 //查询
#define N 512
typedef struct MSG
{
    int type;         // 1为管理员,2为普通用户
    int type2;        //用户选项
    char name[16];    //管理员名字
    char pd[128]; //密码或数据
    int age;
    int salary;
    char data[N];
    char data2[N];
    char office[64];
    int flag;
} msg_t;

void do_register(int, msg_t *);
int do_login(int, msg_t *);
void increase_msg(int, msg_t *);
void delete_msg(int, msg_t *);
void modify_msg(int, msg_t *);
void query_msg(int, msg_t *);

int main(int argc, const char *argv[])
{
    if (argc != 3)
    {
        printf("Usage: %s <ip> <port>\n", argv[0]);
        exit(-1);
    }
    //创建套接字
    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (-1 == sockfd)
    {
        PRINT_ERR("socket error");
    }
    //填充服务器网络信息结构体
    struct sockaddr_in client_addr;
    memset(&client_addr, 0, sizeof(client_addr));

    client_addr.sin_family = AF_INET;
    client_addr.sin_addr.s_addr = inet_addr(argv[1]);
    client_addr.sin_port = htons(atoi(argv[2]));
    socklen_t addrlen = sizeof(client_addr);

    //与服务器建立连接
    if (-1 == connect(sockfd, (struct sockaddr *)&client_addr, addrlen))
    {
        PRINT_ERR("connect error");
    }
    //创建表
    msg_t msg;
    int n = 0;
    int m = 2;
    //收发数据
    while (1)
    {
        printf("**************************************\n");
        printf("**************员工管理系统*************\n");
        printf("******1.管理员  2.普通用户  3.退出******\n");
        printf("**************************************\n");
        printf("请选择: ");
        scanf("%d", &n);
        switch (n)
        {
        case 1:
            memset(&msg, 0, sizeof(msg_t));
            msg.type = R; //管理员
            send(sockfd, &msg, sizeof(msg_t), 0);
            goto SELECT;
            break;
        case 2:
            msg.type = L; //普通用户
            send(sockfd, &msg, sizeof(msg_t), 0);
            goto SELECT;
            break;
        case 3:
            close(sockfd);
            exit(0);
        default:
            printf("输入有误,请重新输入\n");
        }
    }
SELECT:
    while (1)
    {
        printf("**************************************\n");
        printf("**************员工管理系统*************\n");
        printf("*****1.注册  2.登录(%d次机会)  3.退出****\n", m);
        printf("**************************************\n");
        printf("请选择:");
        scanf("%d", &n);
        switch (n)
        {
        case 1:
            do_register(sockfd, &msg);
            goto SELECT;
            break;
        case 2:
            m--;
            if (1 == do_login(sockfd, &msg))
            {                      //登录成功
                if (msg.type == 1) //管理员
                {
                    goto ADMIN_LOGIN;
                }
                else if (msg.type == 2) //用户
                {
                    goto LOGIN;
                }
            }
            else
            { //登录失败
                if (m == 0)
                {
                    close(sockfd);
                    exit(0);
                }
                goto SELECT;
            }
            break;
        case 3:
            close(sockfd);
            exit(0);
        default:
            printf("输入有误,请重新输入\n");
        }
    }
ADMIN_LOGIN:
    while (1)
    {
        printf("*****************************管理员界面*********************************\n");
        printf("****             *             *              *             *      *****\n");
        printf("****1.增加员工信息 2.删除员工信息 3.修改员工信息 4.查询员工信息 5.退出****\n");
        printf("***********************************************************************\n");
        printf("请选择:");
        scanf("%d", &n);
        switch (n)
        {
        case 1:
            increase_msg(sockfd, &msg);
            msg.type == R;
            goto ADMIN_LOGIN;
            break;
        case 2:
            delete_msg(sockfd, &msg);
            goto ADMIN_LOGIN;
            break;
        case 3:
            modify_msg(sockfd, &msg);
            goto ADMIN_LOGIN;
            break;
        case 4:
            query_msg(sockfd, &msg);
            goto ADMIN_LOGIN;
            break;
        case 5:
            close(sockfd);
            exit(0);
        default:
            printf("输入有误,请重新输入\n");
        }
    }

LOGIN:
    while (1)
    {
        printf("*****************************用户界面*********************************\n");
        printf("****             *             *             *           *       *****\n");
        printf("****1.查询本人信息              2.修改本人信息                3.退出****\n");
        printf("**********************************************************************\n");
        printf("请选择:");
        scanf("%d", &n);
        switch (n)
        {
        case 1:
            query_msg(sockfd, &msg);
            memset(msg.data2,0,sizeof(msg.data2));
            goto LOGIN;
            break;
        case 2:
            modify_msg(sockfd, &msg);
            break;
        case 3:
            close(sockfd);
            exit(0);
        default:
            printf("输入有误,请重新输入\n");
        }
    }
    //关闭套接字
    close(sockfd);
    return 0;
}
//注册
void do_register(int sockfd, msg_t *msg)
{
    if (msg->type == 1)
    {
        msg->type2 = R;
        printf("请输入你的用户名: ");
        scanf("%s", msg->name);
        printf("请输入你的密码:");
        scanf("%s", msg->pd);
        send(sockfd, msg, sizeof(msg_t), 0);
        recv(sockfd, msg, sizeof(msg_t), 0);
        printf("%s\n", msg->data);
    }
    else if (msg->type == 2)
    {
        msg->type2 = R;
        printf("请输入你的用户名: ");
        scanf("%s", msg->name);
        printf("请输入你的密码:");
        scanf("%s", msg->pd);
        printf("请输入你的年龄:");
        scanf("%d", &(msg->age));
        printf("请输入你的薪资:");
        scanf("%d", &(msg->salary));
        printf("请输入你的职务:");
        scanf("%s", msg->office);

        send(sockfd, msg, sizeof(msg_t), 0);
        recv(sockfd, msg, sizeof(msg_t), 0);
        printf("%s\n", msg->data);
    }
}
//登录
int do_login(int sockfd, msg_t *msg)
{

    char name[16] = {0};
    char pd[64] = {0};
    msg->type2 = L;
    printf("请输入名字:");
    scanf("%s", name);
    strcpy(msg->name, name);
    printf("请输入密码:");
    scanf("%s", pd);
    strcpy(msg->pd, pd);

    send(sockfd, msg, sizeof(msg_t), 0);

    recv(sockfd, msg, sizeof(msg_t), 0);
    printf("msg.pd = %s\n", msg->pd);
    //判断是否登录成功
    if (strncmp(msg->data, "OK", 3) == 0)
    {
        //登录成功返回1
        printf("登录成功\n");
        return 1;
    }
    printf("%s\n", msg->data);
    return 0;
}

//添加员工
void increase_msg(int sockfd, msg_t *msg)
{
    char name[16];
    char passwd[64];
    int age;
    int salary;
    char office[64];
    msg->type = L;  //切换到用户
    msg->type2 = R; //选项1,添加员工信息
    printf("请输入要添加的员工的名字:");
    scanf("%s", name);
    strcpy(msg->name, name);

    printf("请输入要添加员工的密码:");
    scanf("%s", pd);
    strcpy(msg->pd, pd);

    printf("请输入要添加员工的年龄:");
    scanf("%d", &age);
    msg->age = age;

    printf("请输入要添加员工的薪资:");
    scanf("%d", &salary);
    msg->salary = salary;

    printf("请输入要添加员工的职务:");
    scanf("%s", office);
    strcpy(msg->office, office);

    printf("msg.name = %s\n", msg->name);     // admin
    printf("msg.pd = %s\n", msg->pd); // 123

    send(sockfd, msg, sizeof(msg_t), 0);
    recv(sockfd, msg, sizeof(msg_t), 0);
    printf("%s\n", msg->data);
}
//删除员工
void delete_msg(int sockfd, msg_t *msg)
{
    msg->type2 = D;
    printf("请输入要删除的名字:");
    scanf("%s", msg->name);
    send(sockfd, msg, sizeof(msg_t), 0);
    recv(sockfd, msg, sizeof(msg_t), 0);
    printf("%s\n", msg->data);
}
void modify_msg(int sockfd, msg_t *msg)
{
    if (msg->type==1)
    {
        msg->type2 = M;
        printf("请输入要修改信息的员工名字:");
        scanf("%s", msg->name);
        printf("请输入员工的薪资为:");
        scanf("%d", &(msg->salary));
        printf("请输入员工的职位为:");
        scanf("%s", msg->office);
        send(sockfd, msg, sizeof(msg_t), 0);
        recv(sockfd, msg, sizeof(msg_t), 0);
    }else if(msg->type == 2){
        msg->type2 = M;
        printf("请输入你的名字:");
        scanf("%s", msg->name);
        printf("请输入要修改的年龄为:");
        scanf("%d", &(msg->age));
        printf("请输入要修改的密码为:");
        scanf("%s", msg->pd);
        send(sockfd, msg, sizeof(msg_t), 0);
        recv(sockfd, msg, sizeof(msg_t), 0);
    }
    printf("%s\n",msg->data);
}
void query_msg(int sockfd, msg_t *msg)
{
    msg->type2 = Q;
    send(sockfd, msg, sizeof(msg_t), 0);
    recv(sockfd, msg, sizeof(msg_t), 0);
    printf("%s\n", msg->data);
    printf("%10s", msg->data2);
}

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值