C语言小项目-----员工管理系统

news2024/11/20 1:53:39

目录

项目要求:

考虑点:

 实现过程

所用知识点

最终效果如下:


项目要求:

 

考虑点:

服务器端用select监听多个客户端,考虑点在于,公司内部的系统管理系统,不会有太多人每天都登陆,监听1024-4个客户端是够用的,(0,1,2,3被占用)

select会把所有建立连接的套接字都放到一个链表里,当某个套接字(文件描述符)有事件就会留在这个集合中,进行一步步的处理,代码在下面---->

 实现过程

1.服务器端先创建员工数据库,包含两张表(员工表,历史记录表)

2.要建立通信

3.使用io多路复用(select)实现客户端服务器的交互传输(登陆,添加,删除.....)

将每个功能函数进行封装,并且每个功能函数中都要调用历史记录的插入函数,这样历史记录表中才能有数据。

所用知识点

1.tcp/ip 通信的建立过程(套接字,绑定,监听,收发数据)

2.并发服务器---多种方式可实现(多进程,多线程,io多路复用)

3.数据库接口的使用

4.函数封装,结构体传参。代码编写逻辑,每一个功能分步实现。

最终效果如下:

 登陆界面:

 修改:

 删除:

 添加

 查询历史记录

 总结

代码编写过程中遇到不少bug,一开始的思路和扎实的基础相当重要,

遇到错误首先要针对性排查,知道错因

编写代码要条例清晰,一个功能一个功能的实现,每实现一个测试一下,理清思路很重要,毕竟代码相当抽象。

#include <stdio.h>
#include "yg.h"
int updateMaxfd(int maxfd, fd_set readfds);
sqlite3 *create_sqlitedb(void);
int do_login(int sfd, MSG *msg, sqlite3 *db); // 登陆
int ser_add(int sfd, MSG *msgser, sqlite3 *db);
int select_by_name(int sensfd, MSG *msgser, sqlite3 *db);
int select_all(int sensfd, MSG *msgser, sqlite3 *db);
int Change_ser(int sensfd, MSG *msg_ser, sqlite3 *db);
int delete_ser(int sensfd, MSG *msgser, sqlite3 *db);
int history_ser(int sensfd, MSG *msgser, sqlite3 *db);
void insert_history(sqlite3 *db,char *name,char *opera);
//接收发送
void send_recv(int sfd, MSG *msg);
int main(int argc, char const *argv[])
{
    // 打开数据库,创建2张表
    sqlite3 *db;
    db = create_sqlitedb();
    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd < 0)
    {
        ERR("socket failed");
        return -1;
    }
    printf("创建套接字成功\n");
    int reuse = 1;
    if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
    {
        ERR("setsockopt failed");
        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("bind failed");
        return -1;
    }
    printf("绑定成功\n");
    if (listen(sfd, 10) < 0)
    {
        ERR("listen");
        return -1;
    }
    printf("监听设置成功\n");
    fd_set readfds, tempfds;
    // 清空读集合
    FD_ZERO(&readfds);
    FD_ZERO(&tempfds);
    // 把需要的文件描述符放到读集合中
    FD_SET(0, &readfds);
    FD_SET(sfd, &readfds);
    int maxfd = sfd;
    int se;             // 接收select函数返回值
    char buf[128] = ""; // 存放客户端发来的信息
    MSG msgcli;         // 结构体存放客户端发来的消息
    ssize_t res = 0;
    int newfd = 0;
    // 定义数组存储客户端的地址信息结构体,客户端不会再有012sfd4个去掉
    struct sockaddr_in cinaddr[1024 - 4];
    struct sockaddr_in cin; // cin存放客户端的IP端口
    socklen_t cinlen = sizeof(cin);
    int i = 0;
    while (1)
    {
        tempfds = readfds;
        se = select(maxfd + 1, &tempfds, NULL, NULL, NULL);
        if (se < 0)
        {
            ERR("select failed");
            return -1;
        }
        else if (0 == se)
        {
            printf("time out\n");
            break;
        }
        // 此时有事件发生,判断哪个文件描述符有事件触发
        for (i = 0; i <= maxfd && se != 0; i++)
        {
            // 对监听到的文件描述符做判断
            if (FD_ISSET(i, &tempfds))
            {
                // 该文件描述符在集合中,执行操作
                se--; // 当se==0就绪个数处理完成
                if (0 == i)
                {
                    // 向客户端发送消息
                    int sendfd;
                    bzero(&msg, sizeof(MSG));
                    res = scanf("%d %s", &sendfd, buf);
                    while (getchar() != 10)
                        ;
                    printf("sendfd=%d %s\n", sendfd, buf);
                    if (res != 2)
                    {
                        fprintf(stderr, "请输入正确的格式:fd string\n");
                        continue;
                    }
                    if (sendfd <= 3 || FD_ISSET(sendfd, &readfds) == 0)
                    {
                        fprintf(stderr, "输入文件描述符有误%d\n", sendfd);
                        continue;
                    }
                    if (send(sendfd, buf, sizeof(buf), 0) < 0)
                    {
                        ERR("send");
                        return -1;
                    }
                    printf("发送成功\n");
                }
                else if (sfd == i)
                {
                    // 客户端连接
                    newfd = accept(sfd, (struct sockaddr *)&cin, &cinlen);
                    if (newfd < 0)
                    {
                        ERR("accept");
                        return -1;
                    }
                    // 连接成功
                    printf("[%s:%d] newfd=%d客户端连接成功\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd);
                    // 将客户端的地址信息结构体转存到数组中
                    cinaddr[newfd - 4] = cin;
                    // 将新连接的newfd添加到readfds集合中
                    FD_SET(newfd, &readfds);
                    // 更新maxfd
                    maxfd = maxfd > newfd ? maxfd : newfd;
                }
                else
                {

                    // 客户端交互
                    bzero(msg, sizeof(MSG));
                    // i连接成功的文件描述符
                    // 接收到的消息放到msgcli结构体中
                    // printf("yes\n");
                    res = recv(i, msg, sizeof(MSG), 0);
                    if (res < 0)
                    {
                        ERR("recv");
                        return -1;
                    }
                    else if (0 == res)
                    {
                        fprintf(stderr, "[%s:%d] newfd=%d客户端关闭\n", inet_ntoa(cinaddr[i - 4].sin_addr), ntohs(cinaddr[i - 4].sin_port), i);
                        printf("%s\n", buf);
                        close(i); // 关闭不需要的文件描述符
                        FD_CLR(i, &readfds);
                        maxfd = updateMaxfd(maxfd, readfds);
                    }
                    else
                    {
                        // res>0收到客户端的消息----做相应处理
                        fprintf(stderr, "[%s:%d] newfd=%d客户\n", inet_ntoa(cinaddr[i - 4].sin_addr), ntohs(cinaddr[i - 4].sin_port), i);
                        char type = msg->msgtype;
                        switch (type)
                        {
                        case 'L': // 登陆
                            do_login(i, msg, db);
                            break;
                        case 'u': // 登陆
                            printf("%c\n", msg->msgtype);
                            if(msg->info.usertype=='u')
                            {
                                do_login(i, msg, db);
                            }
                            break;
                        case 'A':
                            ser_add(i, msg, db);
                            break;
                        case 'F':
                            //人名查找
                            select_by_name(i,msg,db);
                            break;
                        case 's':
                            select_all(i,msg,db);
                            break;
                        case 'C':
                        //修改
                            Change_ser(i,msg,db);    
                            break;
                        case 'D':
                        //删除
                            delete_ser(i,msg,db);
                            break;
                        case 'H':
                            history_ser(i,msg,db);
                            break;
                        }
                    }
                }
            }
        }
    }
    close(sfd);
    return 0;
}

// 查询历史记录
int history_ser(int sensfd, MSG *msgser, sqlite3 *db)
{
    char sql[] = "select * from history"; // 存放数据库查询语句
    char **pres = NULL; // 存放数据库查询到的首地址
    int row,column,i,j,k=0;
    insert_history(db,msgser->info.name,sql);
    bzero(msgser->recvmsg,sizeof(msgser->recvmsg));
    if (sqlite3_get_table(db, sql, &pres, &row, &column, NULL) != 0)
    {       
        //用户名密码错误
        ERR_sqlite3(db);
        return -1;
    }else if(0==row)
    {   //
        sprintf(msgser->recvmsg,"没有记录");
        exit -1;
    }else{
        
        for(i=0;i<=row;i++)
        { 
            for(j=0;j<column;j++)
            {
                sprintf(msgser->recvmsg+strlen(msgser->recvmsg),"%s\t",pres[k++]); 
            }
            strcat(msgser->recvmsg,"\n");
        }
       
    }
    if(send(sensfd, msgser, sizeof(MSG), 0) < 0)
    {
        ERR("send");
        return -1;
    }
    printf("返回历史记录\n");
    printf("%s\n",msg->recvmsg);
    return 0;
}
//向历史记录表插入数据
void insert_history(sqlite3 *db,char *name,char *opera)
{
    char sql[256]="";
    char* errmsg = NULL;
    char l_time[32] = "";
	time_t t = time(NULL);
    //info指向获取当前时间的地址
	struct tm* info = localtime(&t);
	sprintf(l_time, "%d-%02d-%02d %02d:%02d",info->tm_year+1900, info->tm_mon+1, info->tm_mday,\
			info->tm_hour, info->tm_min);

	bzero(sql, sizeof(sql));
	sprintf(sql, "insert into history values(\"%s\", \"%s\", \"%s\")", \
			 l_time,name,opera);
	//printf("sql = %s %d\n", sql, __LINE__);

	if(sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
	{
		ERR_sqlite3(db);
		return ;
	}
	printf("插入历史记录成功\n");
    return ;
}

// 退出---
// 删除信息
int delete_ser(int sensfd, MSG *msgser, sqlite3 *db)
{
    char sql[128]="";
    char *errmsg=NULL;

    sprintf(sql,"delete from yginfo where name=\"%s\";",msgser->info.name);
    if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
    {
        ERR_sqlite3(db);
        return -1;
    }
    //删除成功--反馈给客户端
    bzero(msg,sizeof(MSG));
    sprintf(msgser->recvmsg,"%s删除成功",msgser->info.name);
    if(send(sensfd,msgser,sizeof(MSG),0)>0)
    {
        printf("删除成功\n");
    }
    insert_history(db,msgser->info.name,msgser->recvmsg);

}
// 修改员工信息
int Change_ser(int sensfd, MSG *msg_ser, sqlite3 *db)
{   
    MSG chan_info;//此结构体用来接收要修改的信息
    char sql[128]="";
    char *errmsg=NULL;
    char name[30]="";
    strcpy(name,msg_ser->info.name);//插入到历史记录表中
    //判断要修改员工在不在数据库中
    select_by_name(sensfd,msg_ser,db);
    //接收要修改的字段
    if(recv(sensfd,&chan_info,sizeof(chan_info),0)>0)
    {
    switch(chan_info.msgtype)
    {
    case '1':
		//修改年龄
        bzero(sql,sizeof(sql));

		sprintf(sql,"update yginfo set age=%d where name=\"%s\";",chan_info.info.age,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        bzero(&chan_info,sizeof(MSG));
        strcpy(chan_info.recvmsg,"年龄修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("年龄修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	case '2':
		//修改性别>>");
		bzero(sql,sizeof(sql));
        sprintf(sql,"update yginfo set sex=\"%s\" where name=\"%s\";",chan_info.info.sex,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        strcpy(chan_info.recvmsg,"性别修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("性别修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	case '3':
		//修改手机号>>");
		bzero(sql,sizeof(sql));
        sprintf(sql,"update yginfo set tel=\"%s\" where name=\"%s\";",chan_info.info.tel,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        strcpy(chan_info.recvmsg,"手机号修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("手机号修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	case '4':
		//修改密码
        bzero(sql,sizeof(sql));
        sprintf(sql,"update yginfo set passwd=\"%s\" where name=\"%s\";",chan_info.info.passwd,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        strcpy(chan_info.recvmsg,"密码修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("密码修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	case '5':
		//修改家庭住址>>");
        bzero(sql,sizeof(sql));
        sprintf(sql,"update yginfo set addr=\"%s\" where name=\"%s\";",chan_info.info.addr,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        strcpy(chan_info.recvmsg,"家庭住址修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("家庭住址修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	case '6':
		//修改职位>>");
        bzero(sql,sizeof(sql));
        sprintf(sql,"update yginfo set work=\"%s\" where name=\"%s\";",chan_info.info.work,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        strcpy(chan_info.recvmsg,"职位修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("职位修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	case '7':
		//修改入职日期(格式2022.10.10)>>");
        bzero(sql,sizeof(sql));
        sprintf(sql,"update yginfo set date=\"%s\" where name=\"%s\";",chan_info.info.date,msg_ser->info.name);
        if(sqlite3_exec(db,sql,NULL,NULL,&errmsg)!=SQLITE_OK)
        {
            ERR_sqlite3(db);
            return -1;
        }
        //修改成功--反馈给客户端
        strcpy(chan_info.recvmsg,"入职日期修改成功");
        if(send(sensfd,&chan_info,sizeof(chan_info),0)>0)
        {
            printf("入职日期修改成功\n");
        }
        insert_history(db,name,chan_info.recvmsg);
		break;
	}
    }
    return 0;
}
//发送接收
void send_recv(int sfd, MSG *msg)
{
	int res;
    bzero(msg, sizeof(MSG));
	if (send(sfd, msg, sizeof(MSG), 0) < 0)
	{
		ERR("send");
		exit;
	}
	printf("send success\n");
	bzero(msg, sizeof(MSG));
	res = recv(sfd, msg, sizeof(MSG), 0);
	if (res < 0)
	{
		ERR("recv");
		printf("接收失败\n");
		exit;
	}
	else if (0 == res)
	{
		fprintf(stderr, "服务器关闭\n");
		exit;
	}
	printf("接收成功\n");
	return ;
}
//查找所有
int select_all(int sensfd, MSG *msgser, sqlite3 *db)
{
    char sql[] = "select * from yginfo"; // 存放数据库查询语句
    char **pres = NULL; // 存放数据库查询到的首地址
    int row,column,i,j,k=0;
    bzero(msg->recvmsg,sizeof(msg->recvmsg));
    if (sqlite3_get_table(db, sql, &pres, &row, &column, NULL) != 0)
    {
        // 用户名密码错误
        sprintf(msg->recvmsg,"没有员工"); 
        ERR_sqlite3(db);
        return -1;
    }else{
        
        for(i=0;i<=row;i++)
        {
            printf("row=%d,column=%d\n",row,column);
            for(j=0;j<column;j++)
            {
                sprintf(msg->recvmsg+strlen(msg->recvmsg),"%s\t",pres[k++]); 
            }
            strcat(msg->recvmsg,"\n");
        }
       
    }
    if (send(sensfd, msg, sizeof(MSG), 0) < 0)
    {
        ERR("send");
        return -1;
    }
    insert_history(db,msgser->info.name,msg->recvmsg);

}
// 查询信息
int select_by_name(int sensfd, MSG *msgser, sqlite3 *db)
{
    char sql[128] = ""; // 存放数据库查询语句
    char **pres = NULL; // 存放数据库查询到的首地址
    int row,column,i,j,k=0;
    bzero(msg->recvmsg,sizeof(msg->recvmsg));
    sprintf(sql, "select * from yginfo where name=\"%s\";", msg->info.name);
    if (sqlite3_get_table(db, sql, &pres, &row, &column, NULL) != 0)
    {
        //函数执行失败 
        ERR_sqlite3(db);
        return -1;
    }else if(0==row){
        //未找到----用户名密码错误
        sprintf(msg->recvmsg,"没有这个员工");
        msg->msgtype='N';//未找到
    }else{    
        for(i=0;i<=row;i++)
        {
            printf("row=%d,column=%d\n",row,column);
            for(j=0;j<column;j++)
            {
                sprintf(msg->recvmsg+strlen(msg->recvmsg),"%s\t",pres[k++]); 
            }
            strcat(msg->recvmsg,"\n");
        }
        msg->msgtype='O';//成功找到   
    }
    if (send(sensfd, msg, sizeof(MSG), 0) < 0)
    {
        ERR("send");
        return -1;
    }
    insert_history(db,msgser->info.name,msg->recvmsg);
    if(0==row)
    {
        return -1;
    }else return 0;
}
// 登陆
int do_login(int sfd, MSG *msg, sqlite3 *db)
{
    char sql[128] = ""; // 存放数据库查询语句
    char **pres = NULL; // 存放数据库查询到的首地址
    sprintf(sql, "select * from yginfo where name=\"%s\" and passwd=\"%s\";", msg->info.name, msg->info.passwd);
    printf("%s\n", sql);
    if (sqlite3_get_table(db, sql, &pres, NULL, NULL, NULL) != 0)
    {
        // 用户名密码错误
        printf("用户名或密码错误\n");
        ERR_sqlite3(db);
        return -1;
    }
    else
    {
        // 可以登陆
        bzero(msg, sizeof(MSG));
        strcpy(msg->recvmsg, "login_ok");
    }
    // 给客户端传递可登陆信号 
    if (send(sfd, msg, sizeof(MSG), 0) < 0)
    {
        ERR("send");
        return -1;
    }
    insert_history(db,msg->info.name,msg->recvmsg);
    printf("可登陆,发送成功\n");
    return 0;
}
// 更新select文件描述符
int updateMaxfd(int maxfd, fd_set readfds)
{
    for (int j = maxfd; j >= 0; j--)
    {
        if (FD_ISSET(j, &readfds))
        {
            return j;
        }
    }
    return 0;
}
sqlite3 *create_sqlitedb(void)
{
    sqlite3 *db;
    char *errmsg = NULL; // 指向错误信息的地址
    if (sqlite3_open("./yuangong.db", &db) != SQLITE_OK)
    {

        ERR_sqlite3(db);
        return NULL;
    }
    printf("数据库创建成功\n");
    // 创建员工信息表
    char sql[128] = "create table if not exists yginfo(name char,age int,sex char,work char,tel char,addr char,passwd char,date char,usertype char)";
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        ERR_sqlite3(db);
        return NULL;
    }
    printf("员工表创建成功\n");
    // 创建历史记录表
    sprintf(sql, "create table if not exists history(time char,name char,opera char)");
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != SQLITE_OK)
    {
        ERR_sqlite3(db);
        return NULL;
    }
    printf("历史记录表创建成功\n");
    return db;
}
// 添加员工信息
int ser_add(int sfd, MSG *msg, sqlite3 *db)
{

    int ret_value = 0;
    char *errmsg = NULL;
    char sql[512] = "";
    sprintf(sql, "insert into yginfo values(\"%s\", %d,\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",%c);", msg->info.name,msg->info.age, msg->info.sex, msg->info.work, msg->info.tel, msg->info.addr, msg->info.passwd, msg->info.date,msg->info.usertype);
    printf("%s", sql);
    if (sqlite3_exec(db, sql, NULL, NULL, &errmsg) != 0)
    {
        printf("sqlite3_exec:%s %d\n", errmsg, __LINE__);
        strcpy(msg->recvmsg, "插入失败");
        ret_value = -1;
    }
    else
    {
        printf("添加成功\n");
        strcpy(msg->recvmsg, "添加成功");
    }
    if (send(sfd, msg, sizeof(MSG), 0) < 0)
    {
        ERR("send");
        ret_value = -1;
    }
    insert_history(db,msg->info.name,msg->recvmsg);
    return ret_value;
}

客户端

#include "yg.h"
int init_inet(void); //网络初始化
void send_recv(int sfd, MSG *msg);//接收发送
int do_login(int sfd);//登陆
int root_login(int sfd,MSG *msg);//管理员登陆
int root_menu(int sfd);//管理员登陆界面
int user_login(int sfd,MSG *msg);//普通用户登陆
// root用户功能函数
int Select_fun(int sfd);//查询
int Change_fun(int sfd);//修改
void change_by_name(int sfd);//查找名字修改
int Add_fun(int sfd);//添加
int Delete_fun(int sfd);//删除
int History(int sfd);//历史记录

//普通用户功能函数

int main(int argc, const char *argv[])
{
	int sfd = init_inet(); //连接服务器
	while (1)
	{
		//system("clear");
		printf("****************\n");
		printf("*****1.登录*****\n");
		printf("*****2.退出*****\n");
		printf("****************\n");
		scanf("%c", &choose);
		while (getchar() != 10);
		switch (choose)
		{
		case '1':
			msg->msgtype='L';
			do_login(sfd);
			break;
		case '2':
			close(sfd);
			exit(0);
		}
	}

	close(sfd);
	return 0;
}
int do_login(int sfd)
{
	while (1)
	{
		printf("******0.管理员root********\n");
		printf("******1.普通员工user******\n");
		printf("******2.退出     *********\n");
		printf("按数字键选择>>");
		scanf("%c", &choose);
		while(getchar()!=10);
		switch (choose)
		{
		case '0':
			msg->info.usertype='L';
			root_login(sfd,msg);
			break;
		case '1':
			msg->info.usertype='U';
			user_login(sfd,msg);
			break;
		case '2':
			exit(-1);
		}
	}
	return 0;
}

int root_menu(int sfd)
{
	int flag = 0; //返回上级标志位
	char a;

	while (1)
	{
		if (flag == 1)
		{
			break;
		}
		system("clear");
		printf("******1.查询*******\n");
		printf("******2.修改*******\n");
		printf("******3.添加*******\n");
		printf("******4.删除*******\n");
		printf("******5.历史记录****\n");
		printf("******6.退出********\n");
		printf("*****按数字键选择*****\n");
		scanf("%c", &a);
		while(getchar()!=10);
		switch (a)
		{
		case '1':
			Select_fun(sfd);
			break;
		case '2':
			Change_fun(sfd);
			break;
		case '3':
			Add_fun(sfd);
			break;
		case '4':
			Delete_fun(sfd);
			break;
		case '5':
			History(sfd);
			break;
		case '6':
			flag = 1;
			break;
		}
	}
	return 0;
}
int Change_fun(int sfd)
{	
	msg->msgtype='C';
	printf("请输入要修改的用户名>>");
	scanf("%s", msg->info.name);
	while(getchar()!=10);
	if (send(sfd, msg, sizeof(MSG), 0) < 0)
	{
		ERR("send");
		return -1;
	}
	printf("要修改的用户名%s", msg->info.name);
	printf("send success---------\n");
	bzero(msg, sizeof(MSG));
	res = recv(sfd, msg, sizeof(MSG), 0);
	if (res < 0)
	{
		ERR("recv");
		return -1;
	}
	else if (0 == res)
	{
		fprintf(stderr, "服务器关闭\n");
		return -1;
	}
	if(strcmp(msg->recvmsg, "没有这个员工")==0)
	{ //用户不存在
		printf("没有这个员工>>");
	}else if(msg->msgtype='O')
	{
		change_by_name(sfd); //发送要修改的字段
	}
	return 0;
}
//根据名字修改某字段
void change_by_name(int sfd)
{
	printf("******1.年龄****\n");
	printf("******2.性别********\n");
	printf("******3.手机号*****\n");
	printf("******4.密码*****\n");
	printf("******5.家庭住址*****\n");
	printf("******6.职位*****\n");
	printf("******7.入职年月*****\n");
	printf("请输入要修改的字段>>");
	scanf("%c", &choose);
	while(getchar()!=10);
	switch (choose)
	{
	case '1':
		msg->msgtype='1';
		printf("输入年龄>>");
		scanf("%d", &msg->info.age);
		while(getchar()!=10);
		send_recv(sfd,msg);
		break;
	case '2':
		msg->msgtype='2';
		printf("输入性别>>");
		scanf("%s", msg->info.sex);
		while(getchar()!=10);
		send_recv(sfd,msg);
		break;
	case '3':
		msg->msgtype='3';
		printf("输入手机号>>");
		scanf("%s", msg->info.tel);
		while(getchar()!=10);
		send_recv(sfd,msg);
		break;
	case '4':
		msg->msgtype='4';
		printf("输入密码>>");
		scanf("%s", msg->info.passwd);
		while(getchar()!=10);
		send_recv(sfd,msg);
		break;
	case '5':
		msg->msgtype='5';
		printf("输入家庭住址>>");
		scanf("%s", msg->info.addr);
		while(getchar()!=10);
		send_recv(sfd,msg);		
		break;
	case '6':
		msg->msgtype='6';
		printf("输入职位>>");
		scanf("%s", msg->info.work);
		while(getchar()!=10);
		send_recv(sfd,msg);
		break;
	case '7':
		msg->msgtype='7';
		printf("输入入职日期(格式2022.10.10)>>");
		scanf("%s", msg->info.date);
		while(getchar()!=10);
		send_recv(sfd,msg);
		break;
	}
	printf("请输入返回上一级>>>");
	while(getchar()!=10);
	return ;
}
int Add_fun(int sfd)
{
	bzero(msg,sizeof(MSG));
	printf("请输入姓名>>");
	scanf("%s",msg->info.name);
	while(getchar()!=10);

	printf("请输入年龄>>");
	scanf("%d",&msg->info.age);
	while(getchar()!=10);

	printf("请输入性别>>");
	scanf("%s",msg->info.sex);
	while(getchar()!=10);

	printf("请输入职位>>");
	scanf("%s",msg->info.work);
	while(getchar()!=10);

	printf("请输入电话>>");
	scanf("%s",msg->info.tel);
	while(getchar()!=10);

	printf("请输入家庭住址>>");
	scanf("%s",msg->info.addr);
	while(getchar()!=10);

	printf("请输入密码>>");
	scanf("%s",msg->info.passwd);
	while(getchar()!=10);

	printf("请输入入职日期>>");
	scanf("%s",msg->info.date);
	while(getchar()!=10);

	printf("请输入用户类型root(0) user(1)>>");
	scanf("%c",&msg->info.usertype);
	while(getchar()!=10);

	MSG *recv_ser;
	msg->msgtype='A';
	send_recv(sfd,msg);
	printf("%s\n",recv_ser->recvmsg);
	return 0;
}
int Delete_fun(int sfd)
{	msg->msgtype='D';
	printf("请输入要删除的员工姓名>>");
	scanf("%s",msg->info.name);
	send_recv(sfd,msg);
	printf("%s\n",msg->recvmsg);
	return 0;
}
int History(int sfd)
{
	msg->msgtype='H';
	strcpy(msg->info.name,"admin");
	send_recv(sfd,msg);
	printf("shchu\n");
	printf("%s\n",msg->recvmsg);
	return 0;
}
int Select_fun(int sfd)
{
	int quit = 0;
	while (1)
	{
		if (quit == 1)
		{
			break;
		}
		
		printf("******1.按人名查找*******\n");
		printf("******2.查找所有  *******\n");
		printf("******0.返回上一级*******\n");
		scanf("%c", &choose);	
		while(getchar()!=10);
		switch (choose)
		{
		case '0':
			quit = 1;
			break;
		case '1':
			msg->msgtype='F'; //server端通过此知道是人名查找
			printf("请输入要查找的人名>>");
			scanf("%s", msg->info.name);
			while(getchar()!=10);
			if (send(sfd, msg, sizeof(MSG), 0) < 0)
			{
				ERR("send");
				return -1;
			}
			bzero(msg, sizeof(MSG));
			res = recv(sfd, msg, sizeof(MSG), 0);
			if (res < 0)
			{
				ERR("recv");
				return -1;
			}
			else if (0 == res)
			{
				fprintf(stderr, "服务器关闭\n");
				break;
			}
			//打印查找内容
			printf("%s", msg->recvmsg);
			break;
		case '2':
			bzero(msg, sizeof(MSG));
			msg->msgtype='s';//查找所有
			if (send(sfd, msg, sizeof(MSG), 0) < 0)
			{
				ERR("send");
				return -1;
			}
			bzero(msg, sizeof(MSG));
			res = recv(sfd, msg, sizeof(MSG), 0);
			if (res < 0)
			{
				ERR("recv");
				return -1;
			}
			else if (0 == res)
			{
				fprintf(stderr, "服务器关闭\n");
				break;
			}
			//打印查找内容
			printf("%s", msg->recvmsg);
			break;
		}
	}
}
//普通用户登陆
int user_login(int sfd,MSG *msg)
{
	int res;
	char a;
	printf("输入用户名>>");
	scanf("%s", msg->info.name);
	while(getchar()!=10);
	printf("请输入密码>>");
	scanf("%s", msg->info.passwd);
	while(getchar()!=10);
	//发送给服务器
	if (send(sfd, msg, sizeof(MSG), 0) < 0)
	{
		ERR("send");
		return -1;
	}
	printf("send success\n");
	//接收前清空,判断是否登陆成功
	bzero(msg, sizeof(MSG));
	res = recv(sfd, msg, sizeof(MSG), 0);
	if (res < 0)
	{
		ERR("recv");
		return -1;
	}
	else if (0 == res)
	{
		fprintf(stderr, "服务器关闭\n");
		exit(-1);
	}
	else
	{
		if (strcmp(msg->recvmsg, "login_ok"))
		{
			//登陆失败
			printf("用户名或密码错误\n");
			exit(-1);
		}
		else
		{
			//登陆成功---跳转普通用户界面
			printf("1.查询\n");
			printf("2.修改\n");
			printf("3.历史记录\n");

			scanf("%s",&a);
			while(getchar()!=10);
		}
	}
	return 0;
}
//管理员登陆
int root_login(int sfd,MSG *msg)
{
	int res;
	printf("输入用户名>>");
	scanf("%s", msg->info.name);
	while(getchar()!=10);
	printf("请输入密码>>");
	scanf("%s", msg->info.passwd);
	while(getchar()!=10);
	//发送给服务器
	if (send(sfd, msg, sizeof(MSG), 0) < 0)
	{
		ERR("send");
		return -1;
	}
	printf("send success\n");
	//接收前清空,判断是否登陆成功
	bzero(msg, sizeof(MSG));
	res = recv(sfd, msg, sizeof(MSG), 0);
	if (res < 0)
	{
		ERR("recv");
		return -1;
	}
	else if (0 == res)
	{
		fprintf(stderr, "服务器关闭\n");
		exit(-1);
	}
	else
	{
		if (strcmp(msg->recvmsg, "login_ok"))
		{
			//登陆失败
			printf("用户名或密码错误\n");
			exit(-1);
		}
		else
		{
			//登陆成功---跳转管理员菜单
			root_menu(sfd);
		}
	}
	return 0;
}
void send_recv(int sfd, MSG *msg)
{
	int res;
	if (send(sfd, msg, sizeof(MSG), 0) < 0)
	{
		ERR("send");
		exit;
	}
	printf("send success\n");
	bzero(msg, sizeof(MSG));
	res = recv(sfd, msg, sizeof(MSG), 0);
	if (res < 0)
	{
		ERR("recv");
		printf("接收失败\n");
		exit;
	}
	else if (0 == res)
	{
		fprintf(stderr, "服务器关闭\n");
		exit;
	}
	printf("接收成功\n");
	printf("%s\n",msg->recvmsg);
	return ;
}
//网络初始化
int init_inet()
{
	//创建流式套接字
	int sfd = socket(AF_INET, SOCK_STREAM, 0);
	if (sfd < 0)
	{
		ERR("socket");
		return -1;
	}
	int reuse = 1;
	if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
	{
		ERR("setsockopt failed");
		return -1;
	}
	//填充要连接的服务器的IP和端口
	struct sockaddr_in sin;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(PORT);
	sin.sin_addr.s_addr = inet_addr(IP);
	//连接服务器
	if (connect(sfd, (struct sockaddr *)&sin, sizeof(sin)) < 0)
	{
		ERR("connect");
		return -1;
	}
	return sfd;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/80700.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【web前端开发】CSS的元素显示模式

前言 元素的显示模式可以更好的帮助我们布局页面,了解元素的显示模式,可以让我们布局页面时更加简单清晰 什么是元素显示模式 元素显示模式就是元素(标签)以什么样的方式进行显示 HTML元素一般分为块元素和行内元素两种类型 以下是块级元素和行内元素在网页中的显示: 块元…

3.神经网络-深度学习入门

3.神经网络 深度学习入门 本文的文件和代码链接&#xff1a;github地址 1.激活函数 sigmoid h(x)11e−xh(x) \frac{1}{1 e^{-x}} h(x)1e−x1​ def sigmod(x):return 1 / (1 np.exp(-1 * x))ReLU h(x){x:x>00:x≤0h(x) \left\{ \begin{array}{lr} x & : x > …

CMake静态库和动态库构建实例

任务 建⽴⼀个静态库和动态库&#xff0c;提供 HelloFunc 函数供其他程序编程使⽤&#xff0c;HelloFunc 向终端输出 Hello World 字 符串。安装头⽂件与共享库。 构建过程 构建动态库 目录结构 jyhlinuxubuntu:~/share/makefile_cmake/cmake01$ tree . ├── build #在…

m基于多用户MIMO系统的分布式可重构注水算法的matlab仿真

目录 1.算法描述 2.仿真效果预览 3.MATLAB核心程序 4.完整MATLAB 1.算法描述 在单用户MIMO场景中&#xff0c;空间复用技术能够带来高数据速率的传输&#xff0c;但是也需要一些前提条件&#xff0c;比如发射端的预编码或者接收端的信道估计与信号检测。然而&#xff0c;在…

java项目-第169期ssm二手交易平台网站-ssm毕业设计_计算机毕业设计

java项目-第169期ssm二手交易平台网站-ssm毕业设计 【源码请到下载专栏下载】 《ssm二手交易平台网站》 该项目分为3个角色&#xff0c;管理员、用户、商家。 用户可以浏览前台商品并且进行购买。在个人后台可以看到自己的商品。 商家可以对商品进行商品分类管理、商品信息管理…

React 学习笔记:组件通信

组件通信 组件为什么需要通信呢&#xff1f;这是因为组件是独立且封闭的单元&#xff0c;默认情况下&#xff0c;组件只能使用自己的数据&#xff0c;但是多个组件之间不可避免的要共享某些数据&#xff0c;为了实现这些功能&#xff0c;就需要打破组件的独立封闭性&#xff0…

深度学习入门(五十九)循环神经网络——通过时间反向传播

深度学习入门&#xff08;五十九&#xff09;循环神经网络——通过时间反向传播前言循环神经网络——通过时间反向传播教材1 循环神经网络的梯度分析1.1 完全计算1.2 截断时间步1.3 随机截断1.4 比较策略2 通过时间反向传播的细节3 小结前言 核心内容来自博客链接1博客连接2希…

基于java+springboot+vue+mysql的甜品蛋糕销售商城网站

项目介绍 随着社会的快速发展&#xff0c;计算机的影响是全面且深入的。人们生活水平的不断提高&#xff0c;日常生活中用户对网上蛋糕商城方面的要求也在不断提高&#xff0c;网上蛋糕商城得到广大用户的青睐&#xff0c;使得网上蛋糕商城的开发成为必需而且紧迫的事情。本系…

Docker笔记--使用数据卷实现容器与宿主机的数据交互

1--数据卷的介绍和作用 在 Docker 架构中&#xff0c;宿主机系统和容器之间不能直接传递数据&#xff0c;同时当容器被删除时&#xff0c;容器所有的数据都会被清除&#xff1b; 数据卷能够在宿主机与容器、容器与容器之间搭建数据传输和共享的通道&#xff0c;当容器内的目录与…

C++ 快速复习-数据类型

内置数据类型 int、unsigned int 、long、unsigned long 、short、char、signed char、bool、 long long float、double、long double 等 无符号的数据类型 主要在于 不在区分 -&#xff0c;数据波动范围变大。另外&#xff0c;值得注意的是 unsigned 类型的数据 不建议在输出…

玩以太坊链上项目的必备技能(变量作用域-Solidity之旅五)

在前文我们讲过 Solidity 是一种静态类型的语言&#xff0c;这就意味着在声明变量前需先指定类型。 而 Solidity 对变量划分了以下三种作用域范围&#xff1a; 状态变量&#xff08;State Variable&#xff09;&#xff1a; ​ 该变量的值被永久地存放在合约存储中&#xff…

JS新年倒计时

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;前端案例分…

Java---线程详解

目录 一、线程的介绍 二、线程的使用 &#xff08;1&#xff09;多线程的实现 1&#xff1a;继承Thread类 2&#xff1a;实现Runnable接口 &#xff08;2&#xff09;设置和获取线程名称 1:继承Thread类 2&#xff1a;实现Runnable接口 &#xff08;3&#xff09;线程…

Java学习—多线程Thread

多线程1. 线程简介1.1 普通方法和多线程1.2 程序、进程、线程2. 线程创建2.1 Thread类案例&#xff1a;下载图片2.2 Runnable接口案例&#xff1a;龟兔赛跑2.3 Callable接口3. 静态代理4. Lamda表达式5. 线程状态5.1 线程方法5.2 停止线程5.3 线程休眠5.4 线程礼让-yield5.5 Jo…

揭秘SpringMVC-DispatcherServlet之九大组件(二)

前言 上回聊到了HandlerAdapter&#xff0c;今天继续聊后面的组件。今天的主角是HandlerMapping&#xff0c;这篇文章全为他服务了。 HandlerMapping 上回说的Handler&#xff0c;我们说是处理特定请求的。也就是说&#xff0c;不是所有的请求都能处理。那么问题来了&#x…

gateway初始化与配置

1、排除依赖 spring-boot-starter-webflux 2、添加依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency><groupId>org.springf…

基于GDAL的JAVA生成GDB文件实战

前言 在之前博客中&#xff0c;陆续的介绍了关于gdb文件的读取&#xff0c;gis利器之Gdal&#xff08;三&#xff09;gdb数据读取&#xff0c;玩转GDAL一文带你深入Windows下FileGDB驱动支持&#xff0c;这些文章主要都是介绍gdal的读取gdb以及简单的gdb文件读写。在实际工作中…

VJ个人周赛

A:模拟 题意&#xff1a;给定了N个任务&#xff0c;每个任务都有一个优先级&#xff08;1~9&#xff09;&#xff0c;数字越大&#xff0c;优先级越高。将这些任务放入队列中&#xff0c;如果出队的元素&#xff08;x&#xff09;&#xff0c;x的优先级不是最高的&#xff0c;那…

从高级测试到测试开发有什么感悟

最近加入了新的团队&#xff0c;角色发生较大的转变&#xff0c;在这里分享一下自己的感受。 测试的划分 如果我们把产品的生产看成一个流水线的话&#xff0c;那么测试就是流水线上的一个重要岗位&#xff0c;把控着产品的质量。 当然&#xff0c;产品类型的不同&#xff0…

信息系统安全管理

信息系统安全是一个绕不开的话题。从事IT行业&#xff0c;不论何种角色&#xff0c;哪个工种&#xff0c;都需要有所了解。 一、信息系统安全策略 1、概述 信息系统安全策略是指对&#xff08;本单位&#xff09;信息系统的安全风险&#xff08;安全威胁&#xff09;进行有效…