Linux下基于文本文件的员工管理系统,本地版本和基于Socket的Server和Client版本

Linux下基于文本文件的员工管理系统,本地和基于socket的Server端和Client端

一、基本要求

1、Linux环境实现简单的员工管理系统

1) *在Linux系统运行,使用Makefile, *.C源文件分布在两个目录中。
2) *创建基于文本文件的本地员工信息管理系统。
3) *可以增,删,改员工信息。
4) *员工信息包含至少3个数据段,比如工号,英文姓名,年龄,工龄等等。
5) *可以显示所有员工信息。
6) *可以按照关键字检索显示匹配的员工信息。比如:
• 查找某工号的员工
• 查找年龄大于或者小于多少的员工
7) 本地保存的信息按照某个字段排序。
8) *应用程序需要有指令帮助信息,自行设计指令菜单,需要有二级菜单,比如:
※如下只是举例,不用完全按照这个做,但是必须要有二级菜单
********** 菜单 **********
1 - 员工信息查询

  1. 姓名查找
  2. 年龄查找
  3. 工号查找
  4. 返回
    2 - 员工信息更新
  5. 新增员工资料
  6. 删除员工资料
  7. 修改员工资料
  8. 返回
    3 -员工信息排序
  9. 按照年龄排序
  10. 按照工号排序
  11. 返回
    0 – 退出

2、Linux环境实现远程访问员工管理系统

1) *前题目改造成客户端和服务器端的形式。
2) *客户端负责信息输入和输出显示。
3) *服务器端负责数据保存和整理。
4) *客户端和服务器端使用TCP进行沟通。
5) *实现多客户端同时访问服务器功能(增,删,改),包括本地和远程
6) *应用程序需要有命令使用帮助信息


使用双向链表对员工信息进行增删查改和排序,使用文本文件进行员工信息的存储,使用Socket进行Client端和Server端的通信,对于服务器同时响应多个客户端的连接请求,我使用的是多线程。
以下是代码:

二、本地版本

1、List.h

这是双向链表的头文件,包括一些宏。
#ifndef LIST_H
#define LIST_H

#define TO_FILE "/home/liuyin/test/project/test/server/list.data"

typedef struct Node* PNode;
typedef PNode Position;

/*节点结构*/
typedef struct Node
{
    //int data;   //数据域
    char num[20];    //work number
    char name[20];   //name
    char sex[20];    //sex
    char age[20];    //age
    char tel[20];  //phone

    PNode pre;  //前驱指针
    PNode next; //后继指针
}Node;

typedef struct
{
    int size;
    PNode head;
    PNode tail;
}List;

//PNode InitList(List *plist);

//分配节点,并返回节点地址
Position MakeNode();

struct List *Create();

//构造一个空的双向链表
List *InitList();

void clearlist(List *plist);

void clearlist1(List *plist);

//清空链表
void destroylist(List *plist);

//返回头节点地址
Position GetHead(List *plist);
 
//返回尾节点地址
Position GetTail(List *plist);
 
//返回链表大小
int GetSize(List *plist);

//判断链表是否为空
int IsEmpty(List *plist);

//删除头节点
void DelFirst(List *plist);

//删除尾节点
void DelEnd(List *plist);

//删除中间节点
void DelMind(List *plist);

#endif

2、FileManagement.h

这是对文件操作的头文件,因为有用到链表,所以包含了List.h。

#ifndef FILEMANAGEMENT_H
#define FILEMANAGEMENT_H

#include "List.h"

//写入info文件
void WriteFile(List *plist);

//读取info文件
void ReadFile(List *plist);

#endif

3、localhandle.h

这是本地员工管理系统定义的一些操作函数。

#ifndef LOCALHANDLE_H
#define LOCALHANDLE_H

#include "List.h"

//一、员工信息更新,按0返回
//1.新增员工资料
void Add(List *plist);

//2.删除员工资料,按工号删除
void DelNum(List *plist);

//3.修改员工资料
void ChangeNum(List *plist);

//二、员工信息查询
//按工号删除和修改用的查找
PNode FindNum1(List *plist,char *num);

//1.姓名查找
PNode FindName(List *plist);

//2.工号查找
PNode FindNum(List *plist);

//3.年龄查找(大于多少,小于多少)
PNode FindAge(List *plist);

//三、员工信息排序
//1.按年龄排序
void SortAge(List *plist);

//2.按工号排序
void SortNum(List *plist);

//遍历员工信息
void travel(List *plist);

//清空员工信息
void destroy(List *plist);


#endif

4、List.c

对List.h种定义的一些函数进行实现。

#include "List.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//分配节点,并返回节点地址
Position MakeNode()
{
    PNode p = NULL;
    p = (PNode)malloc(sizeof(Node));
    if (NULL != p)
    {
        p->pre = NULL;
        p->next = NULL;
    }
    return p;
}

//构造一个空的双向链表
List *InitList()
{   
    List *plist = (List *)malloc(sizeof(List));
    PNode head = MakeNode();
    if (NULL != plist)
    {
        if (NULL != head)
        {
            plist->head = head;
            plist->tail = head;
            plist->size = 0;
        }
        else
        {
            return NULL;
        }
    }
    return plist;
}

void clearlist(List *plist)
{
    if (NULL == plist->head)
    {
        return;
    }
    PNode p = plist->head->next;
    while (NULL != p)
    {
        PNode temp = p->next;
        free(p);
        p = temp;
    }
    plist->head = NULL;
}

void clearlist1(List *plist)
{
    PNode p = plist->head->next;
    int size = plist->size-1;
    PNode temp = NULL;
    while (size--)
    {
        temp = p;
        p = p->next;
        free(temp);
    }
    plist->size = 1;
}

//清空链表
void destroylist(List *plist)
{
    PNode p = plist->head->next;
    int size = plist->size;
    PNode temp = NULL;
    while (size--)
    {
        //PNode temp = p;
        temp = p;
        p = p->next;
        free(temp);
    }
    plist->size = 0;
}

//返回头节点地址
Position GetHead(List *plist)
{
	return plist->head;
}

//返回尾节点地址
Position GetTail(List *plist)
{
	return plist->tail;
}

//返回链表大小
int GetSize(List *plist)
{
	return plist->size;
}

//判断链表是否为空
int IsEmpty(List *plist)
{
	if(GetSize(plist) == 0 && GetTail(plist) == GetHead(plist))
    {
		return 1;
    }
	else
    {
		return 0;
    }
}

5、FileManagement.c

对文件进行读写操作。

#include "FileManagement.h"
#include "Management.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//写入info文件
void WriteFile(List *plist)
{
    FILE * fp = fopen(TO_FILE,"w");
    if (NULL == fp)
    {
        printf("File Not Found!\n");
        exit(1);
    }

    int size = plist->size;
    PNode q = plist->head->next;
    while (size--)
    {
        fprintf(fp," %s\t %s\t %s\t %s\t %s\t\n",q->num,q->name,q->sex,q->age,q->tel);
        q = q->next;
    }
    fclose(fp);
}

//读取info文件
void ReadFile(List *plist)
{
    destroylist(plist);
    
    FILE *fp = fopen(TO_FILE,"r");
    if (NULL == fp)
    {
        printf("FILE NOT FOUND!");
        exit(1);
    }
    while (0 == feof(fp))
    {
        PNode q = MakeNode();

        fscanf(fp," %s\t %s\t %s\t %s\t %s\t ",q->num,q->name,q->sex,q->age,q->tel);
        if (0 == strcmp(q->num," "))
        {
            break;
        }

        if (0 == plist->size)
        {
            plist->head->next = q;
        }
        else
        {
            plist->tail->next = q;
            q->pre = plist->tail;
        }
        plist->tail = q;
        plist->size++;
    }
    fclose(fp);
}

6、localhandle.c

对员工管理系统的操作函数的实现,有一些写的不是很好,特别是排序的实现,没有体现双向链表的特点。

#include "localhandle.h"
#include "FileManagement.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int inputmsg(char *t)
{
    int n = strcmp(t,"0");
    return n;
}

//一、员工信息更新,按0返回
//1.新增员工资料
void Add(List *plist)
{
    while (1)
    {
        PNode p = MakeNode();
        printf("提示:输入0返回更新员工信息菜单!\n");
        printf("请输入员工工号:\n");
        scanf("%s",p->num);
        if (0 == inputmsg(p->num))
        {
            break;
        }
        printf("请输入员工姓名:\n");
        scanf("%s",p->name);
        if ( 0 == inputmsg(p->name))
        {
            break;
        }
        printf("请输入员工性别:\n");
        scanf("%s",p->sex);
        if ( 0 == inputmsg(p->sex))
        {
            break;
        }
        printf("请输入员工年龄:\n");
        scanf("%s",p->age);
        if ( 0 == inputmsg(p->age))
        {
            break;
        }
        printf("请输入员工电话:\n");
        scanf("%s",p->tel);
        if ( 0 == inputmsg(p->tel))
        {
            break;
        }
        PNode q = FindNum1(plist,p->num);
        if (NULL != q)
        {
            printf("该工号已存在!\n");
            return;
        }
        if (0 == plist->size)//空链表
        {
            plist->head = p;
        }
        else
        {
            plist->tail->next = p;
            p->pre = plist->tail;
        }
        plist->tail = p;
        plist->size++;
        printf("一条员工信息已添加!\n");
        WriteFile(plist);

    }
}

//2.删除员工资料,按工号删除
void DelNum(List *plist)
{
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要删除的员工工号:");
    char num[20];
    scanf("%s",num);
    if (0 == inputmsg(num))
    {
        return;
    }
    PNode p = FindNum1(plist,num);
    if (NULL == p)
    {
        printf("无此员工信息!\n");
        return;
    }
    printf("该员工信息如下:\n");
    printf("\n工号    姓名    性别    年龄    电话\n");
    printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
    //删除头节点
    if (p == plist->head->next)
    {
        plist->head->next = p->next;
    }
    //删除尾节点
    else if (p == plist->tail)
    {
        plist->tail = plist->tail->pre;
    }
    //删除中间节点
    else
    {
        p->pre->next = p->next;
        p->next->pre = p->pre;
        //p->pre->next = p->next;
    } 

    plist->size--;
    free(p);
    WriteFile(plist);
    printf("该员工信息已删除!\n");
}

//3.修改员工资料
void ChangeNum(List *plist)
{
    char num[20];
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要修改的员工工号:");
    scanf("%s",num);
    if (0 == inputmsg(num))
    {
        return;
    }
    PNode p = FindNum1(plist,num);
    if (NULL == p)
    {
        printf("无此员工信息!\n");
        return;
    }
    printf("该员工信息如下:\n");
    printf("\n工号    姓名    性别    年龄    电话\n");
    printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
    printf("请输入新工号:");
    scanf("%s",p->num);
    printf("请输入新姓名:");
    scanf("%s",p->name);
    printf("请输入新性别:");
    scanf("%s",p->sex);
    printf("请输入新年龄:");
    scanf("%s",p->age);
    printf("请输入新电话:");
    scanf("%s",p->tel);

    WriteFile(plist);
    printf("员工信息修改成功!\n");

}

//二、员工信息查询
//按工号删除和修改用的查找
PNode FindNum1(List *plist,char *num)
{
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    while (size--)
    {
        if(0 == strcmp(num,p->num))
        {
            return p;
            break;
        }
        if (NULL != p->next)
        {
            p = p->next;
        }
    }
    if (p == plist->tail && strcmp(num,p->num) != 0)
    {
        return NULL;
    }
}

//1.姓名查找
PNode FindName(List *plist)
{
    char name[20];
    int i = 0;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要查找的员工姓名:");
    scanf("%s",name);
    if (0 == inputmsg(name))
    {
        return;
    }
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    while (size--)
    {
        if(0 == strcmp(p->name,name))
        {
            printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
            i++;
        }
        p = p->next;  
    }
    if (0 == i)
    {
        printf("无此员工信息!\n");
    }
}

//2.工号查找
PNode FindNum(List *plist)
{
    char num[20];
    int i = 0;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要查找的员工工号:");
    scanf("%s",num);
    if (0 == inputmsg(num))
    {
        return;
    }
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    while (size--)
    {
        if(0 == strcmp(p->num,num))
        {
            printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
            i++;
        }
        p = p->next;
    }
    if (0 == i)
    {
        printf("无此员工信息!\n");
    }
}

//3.年龄查找(大于多少,小于多少)
PNode FindAge(List *plist)
{
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    char age[20];
    int choice = 0;
    int i = 0;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要查找的年龄界限:");
    scanf("%s",age);
    if (0 == inputmsg(age))
    {
        return;
    }
    printf("请选择大于或小于此界限:1-小于  2-大于 0-返回 :");
    scanf("%d",&choice);
    if (0 == choice)
    {
        return;
    }
    switch (choice)
    {
        case 1:
            while (size--)
            {
                if(strcmp(age,p->age) >= 0)
                {
                    printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
                    i++;
                }
                p = p->next;
            }
            if (0 == i)
            {
                printf("无此类员工信息!\n");
            }
        break;
        case 2:
            while (size--)
            {
                if(strcmp(age,p->age) <= 0)
                {
                    printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
                    i++;
                }
                p = p->next;
            }
            if (0 == i)
            {
                printf("无此类员工信息!\n");
            }
        break;
        default:
            printf("输入错误!\n");
    }
}

//三、员工信息排序
//1.按年龄排序
void SortAge(List *plist)
{
loop1:
    ReadFile(plist);
    int size = plist->size;
    if (0 == size)
    {
        printf("员工列表为空!\n");
        return;
    }
    PNode p = plist->head->next;
    PNode q = NULL,temp = NULL;
    PNode tp = plist->head->next;
    PNode mov = tp->next;
    PNode phead = plist->head;

    if (p && size >= 2)
    {
        if ((size >= 2) && strcmp(tp->age,mov->age) > 0)
        {
            if (mov->next)
            {
                mov->pre->next = mov->next;
                mov->next->pre = mov->pre;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }
            else
            {
                mov->pre->next = NULL;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }

        }
        for (p = p->next;p;p = p->next)//从第二个开始,第一个默认有序
        {
            temp = p;
            for (q = p->pre;q != plist->head->next;q = q->pre)//q从p的前一节点开始往前
            {
                if (strcmp(q->age,temp->age) <= 0)//升序
                {
                    break;
                }
            }
            if (q->next != p)//如果q有前移,插入temp
            {
                if (temp->next)//temp不为最后一个节点
                {
                    //temp前后互指,分离temp
                    temp->pre->next = temp->next;
                    temp->next->pre = temp->pre;
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
                else//temp是最后一个节点
                {
                    temp->pre->next = NULL;//temp前一节点的next指为NULL
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
            }
        }
    }
    WriteFile(plist);
    PNode cp = plist->head->next;
    PNode cp1 = cp ->next;
    if ((size >= 2) && strcmp(cp->age,cp1->age) > 0)
    {
        goto loop1;
    }
}

//2.按工号排序
void SortNum(List *plist)
{
loop2:
    ReadFile(plist);
    int size = plist->size;
    if (0 == size)
    {
        printf("员工列表为空!\n");
        return;
    }
    PNode p = plist->head->next;
    PNode q = NULL,temp = NULL;
    PNode tp = plist->head->next;
    PNode mov = tp->next;
    PNode phead = plist->head;

    if (p && size >= 2)
    {
        if ((size >= 2) && strcmp(tp->num,mov->num) > 0)
        {
            if (mov->next)
            {
                mov->pre->next = mov->next;
                mov->next->pre = mov->pre;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }
            else
            {
                mov->pre->next = NULL;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }

        }
        for (p = p->next;p;p = p->next)//从第二个开始,第一个默认有序
        {
            temp = p;
            for (q = p->pre;q != plist->head->next;q = q->pre)//q从p的前一节点开始往前
            {
                if (strcmp(q->num,temp->num) <= 0)//升序
                {
                    break;
                }
            }
            if (q->next != p)//如果q有前移,插入temp
            {
                if (temp->next)//temp不为最后一个节点
                {
                    //temp前后互指,分离temp
                    temp->pre->next = temp->next;
                    temp->next->pre = temp->pre;
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
                else//temp是最后一个节点
                {
                    temp->pre->next = NULL;//temp前一节点的next指为NULL
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
            }
        }
    }
    WriteFile(plist);
    PNode cp = plist->head->next;
    PNode cp1 = cp ->next;
    if ((size >= 2) && strcmp(cp->num,cp1->num) > 0)
    {
        goto loop2;
    }
}

//遍历员工信息
void travel(List *plist)
{
    ReadFile(plist);
    int size = plist->size;
    PNode p = plist->head->next;
    printf("员工信息显示如下:\n");
    printf("\n工号    姓名    性别    年龄    电话\n");
    while (size--)
    {
        printf("\n %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
        p = p->next;
    }
    
}

//清空员工信息
void destroy(List *plist)
{
    destroylist(plist);
    WriteFile(plist);
    printf("员工信息已全部清空!\n");
}

7、main函数

#include "localhandle.h"
#include <stdio.h>

//更新员工信息
static void UpdateInfo(List *plist)
{
    int choice = 0;
    while (1)
    {
        printf("=============更新员工信息============\n");
        printf("=           1.新增员工信息          =\n");
        printf("=           2.修改员工信息          =\n");
        printf("=           3.删除员工信息          =\n");
        printf("=           0.返回主菜单            =\n");
        printf("=============更新员工信息============\n");
        printf("请选择:");
        scanf("%d",&choice);
        if (0 == choice)
        {
            break;
        }
        switch (choice)
        {
            case 1:
                Add(plist);
            break;
            case 2:
                ChangeNum(plist);
            break;
            case 3:
                DelNum(plist);
            break;
            default:
                printf("输入错误!\n");
        }
    } 
}

//查询员工信息
static void FindInfo(List *plist)
{

    int choice = 0;
    while (1)
    {
        printf("==============查询员工信息==========\n");
        printf("=           1.按姓名查找           =\n");
        printf("=           2.按工号查找           =\n");
        printf("=           3.按年龄查找           =\n");
        printf("=           0.返回主菜单           =\n");
        printf("==============查询员工信息==========\n");
        printf("请选择:");
        scanf("%d",&choice);
        if (0 == choice)
        {
            break;
        }
        switch (choice)
        {
            case 1:
                FindName(plist);
            break;
            case 2:
                FindNum(plist);
            break;
            case 3:
                FindAge(plist);
            break;
            default:
                printf("输入错误!\n");
        }
    } 
}

//员工信息排序
static void SortInfo(List *plist)
{
    int choice = 0;
    while (1)
    {
        printf("===============员工信息排序==========\n");
        printf("=            1.按工号排序           =\n");
        printf("=            2.按年龄排序           =\n");
        printf("=            0. 返回主菜单          =\n");
        printf("===============员工信息排序==========\n");
        printf("请选择:");
        scanf("%d",&choice);
        if (0 == choice)
        {
            break;
        }
        switch (choice)
        {
            case 1:
                SortNum(plist);
            break;
            case 2:
                SortAge(plist);
            break;
            default:
                printf("输入错误!\n");
        }
    } 
}

int main()
{
    List *plist;

    plist = InitList();

     while(1)
    {
        int choice = 0;
        printf("===============主菜单===============\n");
        printf("=         1.更新员工信息            =\n");
        printf("=         2.查询员工信息            =\n");
        printf("=         3.排序员工信息            =\n");
        printf("=         4.遍历员工信息            =\n");
        printf("=         5.清空员工信息            =\n");
        printf("=         0.    退出                =\n");
        printf("===============主菜单===============\n");

        printf("请选择想要的操作序号:");
        scanf("%d",&choice);

        if (0 == choice)
        {
            printf("欢迎下次使用!\n");
            break;
        }
        switch (choice)
        {
            case 1:
                UpdateInfo(plist);
            break;
            case 2:
                FindInfo(plist);
            break;
            case 3:
                SortInfo(plist);
            break;
            case 4:
                travel(plist);
            break;
            case 5:
                destroy(plist);
            break;
            default:
            printf("输入错误!");
        }
    

    }

    return 0;
}

8、Makefile

OBJ = main.o localhandle.o List.o FileManagement.o

main:$(OBJ)
	gcc -g -o main $(OBJ)

List.o:List.c List.h
	gcc -c List.c

FileManagement.o:FileManagement.c FileManagement.h
	gcc -c FileManagement.c

localhandle.o:localhandle.c localhandle.h
	gcc -c localhandle.c

.PHONY:clear
clear:
	rm main $(OBJ)

9、编译

直接make就行,可以生成可执行文件main。Makefile里加了GDB调试的编译参数,可以使用GDB调试。

三、Server和Client模式

一、Server端

1、List.h

#ifndef LIST_H
#define LIST_H

#define TO_FILE "/home/liuyin/test/project/test/server/list.data"

typedef struct Node* PNode;
typedef PNode Position;

/*节点结构*/
typedef struct Node
{
    //int data;   //数据域
    char num[20];    //work number
    char name[20];   //name
    char sex[20];    //sex
    char age[20];    //age
    char tel[20];  //phone

    PNode pre;  //前驱指针
    PNode next; //后继指针
}Node;

typedef struct
{
    int size;
    PNode head;
    PNode tail;
}List;

//PNode InitList(List *plist);

//分配节点,并返回节点地址
Position MakeNode();

struct List *Create();

//构造一个空的双向链表
List *InitList();

void clearlist(List *plist);

void clearlist1(List *plist);

//清空链表
void destroylist(List *plist);

//返回头节点地址
Position GetHead(List *plist);
 
//返回尾节点地址
Position GetTail(List *plist);
 
//返回链表大小
int GetSize(List *plist);

//判断链表是否为空
int IsEmpty(List *plist);

//删除头节点
void DelFirst(List *plist);

//删除尾节点
void DelEnd(List *plist);

//删除中间节点
void DelMind(List *plist);

#endif

2、FileManagement.h

#ifndef FILEMANAGEMENT_H
#define FILEMANAGEMENT_H

#include "List.h"

//写入info文件
void WriteFile(List *plist);

//读取info文件
void ReadFile(List *plist);

#endif

3、Management.h

Server端收到请求后调用的内部函数。

#ifndef MANAGEMENT_H
#define MANAGEMENT_H

#include "List.h"
#include "Socket.h"

//一、员工信息更新,按0返回
//1.新增员工资料
void Add(List *plist,Msg *msg,int clientfd);

//2.删除员工资料,按工号删除
void DelNum(List *plist,Msg *msg,int clientfd);

//3.修改员工资料
void ChangeNum(List *plist,Msg *msg,int clientfd);

//二、员工信息查询
//按工号删除和修改用的查找
PNode FindNum1(List *plist,char *num);

//1.姓名查找
PNode FindName(List *plist,Msg *msg,int clientfd);

//2.工号查找
PNode FindNum(List *plist,Msg *msg,int clientfd);

//3.年龄查找(大于多少,小于多少)
PNode FindAge(List *plist,Msg *msg,int clientfd);

//三、员工信息排序
//交换节点
void swap(List *plist,PNode s1,PNode s2);
//void SortAge(List *plist,PNode phead,PNode ptail,int n);
//1.按年龄排序
void SortAge(List *plist,Msg *msg,int clientfd);

//2.按工号排序
void SortNum(List *plist,Msg *msg,int clientfd);

//遍历员工信息
void travel(List *plist,Msg *msg,int clientfd);

//清空员工信息
void destroy(List *plist,Msg *msg,int clientfd);

#endif

4、HandleRequest.h

Server端收到Client端的消息后,进入此处理函数,根据类型调用不同的函数。

#ifndef HANDLEREQUEST_H
#define HANDLEREQUEST_H

#include "Socket.h"

void HandleRequest(void *arg);

#endif

5、Socket.h

#ifndef SOCKET_H
#define SOCKET_H

#define TO_FILE "/home/liuyin/test/project/test/server/list.data"
#define MSG_MAX 100

#define PORT 8000
#define ADDRESS "192.168.226.128"
//#define ADDRESS "172.30.51.44"
#define BACKLOG 100
#define MAXLINE 1024

enum MsgType
{
    ADD_INFO = 1,
    UPDATE_INFO,
    DELETE_INFO,
    FIND_NAME,
    FIND_NUM,
    FIND_AGE,
    SORT_NUM,
    SORT_AGE,
    TRAVEL,
    DESTROY
};

typedef struct
{
    int count;
    char type;//消息类型
    char data[100];//消息内容
    char num[20];    //work number
    char name[20];   //name
    char sex[20];    //sex
    char age[20];    //age
    char tel[20];  //phone
}Msg;

#endif

6、List.c

#include "List.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

//分配节点,并返回节点地址
Position MakeNode()
{
    PNode p = NULL;
    p = (PNode)malloc(sizeof(Node));
    if (NULL != p)
    {
        p->pre = NULL;
        p->next = NULL;
    }
    return p;
}

//构造一个空的双向链表
List *InitList()
{   
    List *plist = (List *)malloc(sizeof(List));
    PNode head = MakeNode();
    if (NULL != plist)
    {
        if (NULL != head)
        {
            plist->head = head;
            plist->tail = head;
            plist->size = 0;
        }
        else
        {
            return NULL;
        }
    }
    return plist;
}

void clearlist(List *plist)
{
    if (NULL == plist->head)
    {
        return;
    }
    PNode p = plist->head->next;
    while (NULL != p)
    {
        PNode temp = p->next;
        free(p);
        p = temp;
    }
    plist->head = NULL;
}

void clearlist1(List *plist)
{
    PNode p = plist->head->next;
    int size = plist->size-1;
    PNode temp = NULL;
    while (size--)
    {
        temp = p;
        p = p->next;
        free(temp);
    }
    plist->size = 1;
}

//清空链表
void destroylist(List *plist)
{
    PNode p = plist->head->next;
    int size = plist->size;
    PNode temp = NULL;
    while (size--)
    {
        //PNode temp = p;
        temp = p;
        p = p->next;
        free(temp);
    }
    plist->size = 0;
}

//返回头节点地址
Position GetHead(List *plist)
{
	return plist->head;
}

//返回尾节点地址
Position GetTail(List *plist)
{
	return plist->tail;
}

//返回链表大小
int GetSize(List *plist)
{
	return plist->size;
}

//判断链表是否为空
int IsEmpty(List *plist)
{
	if(GetSize(plist) == 0 && GetTail(plist) == GetHead(plist))
    {
		return 1;
    }
	else
    {
		return 0;
    }
}

7、FileManagement.c

#include "FileManagement.h"
#include "Management.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//写入info文件
void WriteFile(List *plist)
{
    FILE * fp = fopen(TO_FILE,"w");
    if (NULL == fp)
    {
        printf("File Not Found!\n");
        exit(1);
    }

    int size = plist->size;
    PNode q = plist->head->next;
    while (size--)
    {
        fprintf(fp," %s\t %s\t %s\t %s\t %s\t\n",q->num,q->name,q->sex,q->age,q->tel);
        q = q->next;
    }
    fclose(fp);
}

//读取info文件
void ReadFile(List *plist)
{
    destroylist(plist);
    
    FILE *fp = fopen(TO_FILE,"r");
    if (NULL == fp)
    {
        printf("FILE NOT FOUND!");
        exit(1);
    }
    while (0 == feof(fp))
    {
        PNode q = MakeNode();

        fscanf(fp," %s\t %s\t %s\t %s\t %s\t ",q->num,q->name,q->sex,q->age,q->tel);
        if (0 == strcmp(q->num," "))
        {
            break;
        }

        if (0 == plist->size)
        {
            plist->head->next = q;
        }
        else
        {
            plist->tail->next = q;
            q->pre = plist->tail;
        }
        plist->tail = q;
        plist->size++;
    }
    fclose(fp);
}

8、Management.c

#include "Management.h"
#include "FileManagement.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 一、员工信息更新,按0返回
// 1.新增员工资料
void Add(List *plist,Msg *msg,int clientfd)
{
    //ReadFile(plist);
    //printf("提示:输入0返回更新员工信息菜单!\n");
    PNode p = MakeNode();
    strcpy(p->num,msg[0].num);
    strcpy(p->name,msg[0].name);
    strcpy(p->sex,msg[0].sex);
    strcpy(p->age,msg[0].age);
    strcpy(p->tel,msg[0].tel);

    PNode q = FindNum1(plist,p->num);
    if (NULL != q)
    {
        memset(msg,0,sizeof(Msg));
        strcpy(msg[0].data,"工号已存在!");
        strcpy(msg[0].num,"0");
        write(clientfd,msg,sizeof(Msg));
        return;
    }

    if (0 == plist->size)//空链表
    {
        plist->head = p;
    }
    else
    {
        plist->tail->next = p;
        p->pre = plist->tail;
    }
    plist->tail = p;
    plist->size++;
    strcpy(msg[0].data,"一条员工信息已添加!");
    write(clientfd,msg,sizeof(Msg));
    WriteFile(plist);
}

//2.删除员工资料,按姓名删除
//按工号删除和修改用的查找
PNode FindNum1(List *plist,char *num)
{
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    while (size--)
    {
        if(0 == strcmp(num,p->num))
        {
            return p;
            break;
        }
        if (NULL != p->next)
        {
            p = p->next;
        }
    }
    if (p == plist->tail && strcmp(num,p->num) != 0)
    {
        return NULL;
    }
}

//按工号删除
void DelNum(List *plist,Msg *msg,int clientfd)
{
    PNode p = FindNum1(plist,msg[0].num);
    if (NULL == p)
    {
        memset(msg,0,sizeof(Msg));
        strcpy(msg[0].data,"无此员工信息!");
        strcpy(msg[0].num,"0");
        write(clientfd,msg,sizeof(Msg));
        //printf("无此员工信息!\n");
        return;
    }
    memset(msg,0,sizeof(Msg));
    strcpy(msg[0].data,"该员工信息如下:");
    strcpy(msg[0].num,p->num);
    strcpy(msg[0].name,p->name);
    strcpy(msg[0].sex,p->sex);
    strcpy(msg[0].age,p->age);
    strcpy(msg[0].tel,p->tel);
    write(clientfd,msg,sizeof(Msg));

    //删除头节点
    if (p == plist->head->next)
    {
        plist->head->next = p->next;
    }
    //删除尾节点
    else if (p == plist->tail)
    {
        plist->tail = plist->tail->pre;
    }
    //删除中间节点
    else
    {
        p->pre->next = p->next;
        p->next->pre = p->pre;
        //p->pre->next = p->next;
    } 

    plist->size--;
    free(p);
    WriteFile(plist);
    //printf("删除成功!\n");
    return;
}

//3.修改员工资料
void ChangeNum(List *plist,Msg *msg,int clientfd)
{
    PNode p = FindNum1(plist,msg[0].num);
    if (NULL == p)
    {
        memset(msg,0,sizeof(Msg));
        strcpy(msg[0].data,"无此员工信息!");
        strcpy(msg[0].num,"0");
        write(clientfd,msg,sizeof(Msg));
        //printf("无此员工信息!\n");
        return;
    }
    memset(msg,0,sizeof(Msg));
    strcpy(msg[0].data,"该员工信息如下:");
    strcpy(msg[0].num,p->num);
    strcpy(msg[0].name,p->name);
    strcpy(msg[0].sex,p->sex);
    strcpy(msg[0].age,p->age);
    strcpy(msg[0].tel,p->tel);
    write(clientfd,msg,sizeof(Msg));

    memset(msg,0,sizeof(Msg));
    read(clientfd,msg,sizeof(Msg));
    strcpy(p->num,msg[0].num);
    strcpy(p->name,msg[0].name);
    strcpy(p->sex,msg[0].sex);
    strcpy(p->age,msg[0].age);
    strcpy(p->tel,msg[0].tel);

    WriteFile(plist);
    return;
}

//二、员工信息查询
//1.姓名查找
PNode FindName(List *plist,Msg *msg,int clientfd)
{
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    int i = 1;
    while (size--)
    {
        if(0 == strcmp(p->name,msg[0].name))
        {
            strcpy(msg[i].num,p->num);
            strcpy(msg[i].name,p->name);
            strcpy(msg[i].sex,p->sex);
            strcpy(msg[i].age,p->age);
            strcpy(msg[i].tel,p->tel);
            i++;
            msg[0].count = i-1;
        }
        p = p->next;
    }
    //printf("msg[0].count=%d\n",msg[0].count);
    if (1 == i)
    {
        strcpy(msg[0].num,"0");
        strcpy(msg[0].data,"无此员工信息!");
        write(clientfd,msg,sizeof(Msg));
    }
    else
    {
        strcpy(msg[0].data,"员工信息显示如下:");
        write(clientfd,msg,sizeof(Msg[MSG_MAX]));
    }
}

//2.工号查找
PNode FindNum(List *plist,Msg *msg,int clientfd)
{
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    int i = 1;
    //printf("%s\n",msg[0].num);
    while (size--)
    {
        
        if(0 == strcmp(p->num,msg[0].num))
        {
            //memset(msg,0,sizeof(Msg));
            strcpy(msg[0].num,p->num);
            strcpy(msg[0].name,p->name);
            strcpy(msg[0].sex,p->sex);
            strcpy(msg[0].age,p->age);
            strcpy(msg[0].tel,p->tel);
            strcpy(msg[0].data,"员工信息显示如下:");
            write(clientfd,msg,sizeof(Msg));
            // fprintf(fp," %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
            break;
        }
        p = p->next;
        if (size <= 0)
        {
            memset(msg,0,sizeof(Msg));
            strcpy(msg[0].data,"无此员工信息!");
            strcpy(msg[0].num,"0");
            write(clientfd,msg,sizeof(Msg));
        }
    }
}

//3.年龄查找(大于多少,小于多少)
PNode FindAge(List *plist,Msg *msg,int clientfd)
{
    ReadFile(plist);
    PNode p = plist->head->next;
    int size = plist->size;
    int i = 1;
    if (0 == strcmp(msg[0].data,"1"))
    {
        while (size--)
        {
            if (strcmp(msg[0].age,p->age) >= 0)
            {
                strcpy(msg[i].num,p->num);
                strcpy(msg[i].name,p->name);
                strcpy(msg[i].sex,p->sex);
                strcpy(msg[i].age,p->age);
                strcpy(msg[i].tel,p->tel);
                i++;
                msg[0].count = i-1;
                //fprintf(fp," %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
            }
            p = p->next;
        }
    }
    else if (0 == strcmp(msg[0].data,"2"))
    {
        while (size--)
        {
            if (strcmp(msg[0].age,p->age) <= 0)
            {
                strcpy(msg[i].num,p->num);
                strcpy(msg[i].name,p->name);
                strcpy(msg[i].sex,p->sex);
                strcpy(msg[i].age,p->age);
                strcpy(msg[i].tel,p->tel);
                i++;
                msg[0].count = i;
                //fprintf(fp," %s\t %s\t %s\t %s\t %s\t\n",p->num,p->name,p->sex,p->age,p->tel);
            }
            p = p->next;
        }
    }
    if (1 == i)
    {
        strcpy(msg[0].num,"0");
        strcpy(msg[0].data,"无此员工信息!");
        write(clientfd,msg,sizeof(Msg));
    }
    //memset(msg,0,sizeof(Msg));
    strcpy(msg[0].data,"员工信息显示如下:");
    write(clientfd,msg,sizeof(Msg[MSG_MAX]));
}

//三、员工信息排序
//1.按年龄排序
void SortAge(List *plist,Msg *msg,int clientfd)
{
loop1:
    ReadFile(plist);
    int size = plist->size;
    if (0 == size)
    {
        memset(msg,0,sizeof(Msg));
        strcpy(msg[0].data,"员工列表为空!");
        strcpy(msg[0].num,"0");
        write(clientfd,msg,sizeof(Msg));
        return;
    }
    PNode p = plist->head->next;
    PNode q = NULL,temp = NULL;
    memset(msg,0,sizeof(Msg));
    PNode tp = plist->head->next;
    PNode mov = tp->next;
    PNode phead = plist->head;
    if (1 == size)
    {
        strcpy(msg[0].data,"员工信息显示如下:");
    }
    else if (p && size >= 2)
    {
        if ((size >= 2) && strcmp(tp->age,mov->age) > 0)
        {
            if (mov->next)
            {
                mov->pre->next = mov->next;
                mov->next->pre = mov->pre;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }
            else
            {
                mov->pre->next = NULL;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }

        }
        for (p = p->next;p;p = p->next)//从第二个开始,第一个默认有序
        {
            temp = p;
            for (q = p->pre;q != plist->head->next;q = q->pre)//q从p的前一节点开始往前
            {
                if (strcmp(q->age,temp->age) <= 0)//升序
                {
                    break;
                }
            }
            if (q->next != p)//如果q有前移,插入temp
            {
                if (temp->next)//temp不为最后一个节点
                {
                    //temp前后互指,分离temp
                    temp->pre->next = temp->next;
                    temp->next->pre = temp->pre;
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
                else//temp是最后一个节点
                {
                    temp->pre->next = NULL;//temp前一节点的next指为NULL
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
            }
        }
        strcpy(msg[0].data,"员工信息显示如下:");
    }
    //write(clientfd,msg,sizeof(Msg));
    WriteFile(plist);
    PNode cp = plist->head->next;
    PNode cp1 = cp ->next;
    if ((size >= 2) && strcmp(cp->age,cp1->age) > 0)
    {
        goto loop1;
    }
    write(clientfd,msg,sizeof(Msg));
}

//2.按工号排序
void SortNum(List *plist,Msg *msg,int clientfd)
{
loop2:
    ReadFile(plist);
    int size = plist->size;
    if (0 == size)
    {
        memset(msg,0,sizeof(Msg));
        strcpy(msg[0].data,"员工列表为空!");
        strcpy(msg[0].num,"0");
        write(clientfd,msg,sizeof(Msg));
        return;
    }
    PNode p = plist->head->next;
    PNode q = NULL,temp = NULL;
    memset(msg,0,sizeof(Msg));
    PNode tp = plist->head->next;
    PNode mov = tp->next;
    PNode phead = plist->head;
    if (1 == size)
    {
        strcpy(msg[0].data,"员工信息显示如下:");
    }
    else if(p && size >= 2)
    {
        if (strcmp(tp->num,mov->num) > 0)
        {
            if (mov->next)
            {
                mov->pre->next = mov->next;
                mov->next->pre = mov->pre;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }
            else
            {
                mov->pre->next = NULL;
                mov->next = phead->next;
                phead->next->pre = mov;
                mov->pre = phead;
                phead->next = mov;
            }

        }
        for (p = p->next;p;p = p->next)//从第二个开始,第一个默认有序
        {
            temp = p;
            for (q = p->pre;q != plist->head->next;q = q->pre)//q从p的前一节点开始往前
            {
                if (strcmp(q->num,temp->num) <= 0)//升序
                {
                    break;
                }
            }
            if (q->next != p)//如果q有前移,插入temp
            {
                if (temp->next)//temp不为最后一个节点
                {
                    //temp前后互指,分离temp
                    temp->pre->next = temp->next;
                    temp->next->pre = temp->pre;
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
                else//temp是最后一个节点
                {
                    temp->pre->next = NULL;//temp前一节点的next指为NULL
                    //插入temp
                    temp->next = q->next;
                    q->next->pre = temp;
                    temp->pre = q;
                    q->next = temp;
                }
            }
        }
        strcpy(msg[0].data,"员工信息显示如下:");
    }
    //write(clientfd,msg,sizeof(Msg));
    WriteFile(plist);
    PNode cp = plist->head->next;
    PNode cp1 = cp ->next;
    if ((size >= 2) && strcmp(cp->num,cp1->num) > 0)
    {
        goto loop2;
    }
    write(clientfd,msg,sizeof(Msg));
} 

//遍历员工信息
void travel(List *plist,Msg *msg,int clientfd)
{
    ReadFile(plist);
    int size = plist->size;
    PNode p = plist->head->next;
    int i = 0;
    if (0 == plist->size)
    {
        memset(msg,0,sizeof(Msg));
        strcpy(msg[0].data,"员工列表为空!");
        strcpy(msg[0].num,"0");
        write(clientfd,msg,sizeof(Msg));
        return;
    }
    else
    {
        while (size--)
        {
            strcpy(msg[i].num,p->num);
            strcpy(msg[i].name,p->name);
            strcpy(msg[i].sex,p->sex);
            strcpy(msg[i].age,p->age);
            strcpy(msg[i].tel,p->tel);
            msg[0].count = i;
            i++;
            p = p->next;
        }
        strcpy(msg[0].data,"员工信息显示如下:");
        write(clientfd,msg,sizeof(Msg[MSG_MAX]));
    }
}

//清空员工信息
void destroy(List *plist,Msg *msg,int clientfd)
{
    destroylist(plist);
    WriteFile(plist);
    memset(msg,0,sizeof(Msg[MSG_MAX]));
    strcpy(msg[0].data,"员工信息已全部清除!");
    write(clientfd,msg,sizeof(Msg[MSG_MAX]));
}

9、HandleRequest.c

#include "HandleRequest.h"
#include "List.h"
#include <stdio.h>
#include <string.h>

void HandleRequest(void *arg)
{
    printf("This is HandleRequesat!\n");

    List *plist;
    plist =InitList();

    Msg msg[MSG_MAX];
    unsigned int clientfd = *(unsigned int *)arg;
    while (1)
    {
        memset(msg,0,sizeof(Msg[MSG_MAX]));
        read(clientfd,msg,sizeof(Msg[MSG_MAX]));
        if (0 == msg[0].type)
        {
            break;
        }

        switch (msg[0].type)
        {
            case ADD_INFO:
                Add(plist,msg,clientfd);
            break;
            case UPDATE_INFO:
                ChangeNum(plist,msg,clientfd);
            break;
            case DELETE_INFO:
                DelNum(plist,msg,clientfd);
            break;
            case FIND_NAME:
                FindName(plist,msg,clientfd);
            break;
            case FIND_NUM:
                FindNum(plist,msg,clientfd);
            break;
            case FIND_AGE:
                FindAge(plist,msg,clientfd);
            break;
            case SORT_NUM:
                SortNum(plist,msg,clientfd);
                //SortNum(plist,msg,clientfd);
            break;
            case SORT_AGE:
                SortAge(plist,msg,clientfd);
                //SortAge(plist,msg,clientfd);
            break;
            case TRAVEL:
                travel(plist,msg,clientfd);
            break;
            case DESTROY:
                destroy(plist,msg,clientfd);
            break;
            default:
                printf("输入错误!\n");
        }
    }
}

10、Socket.c

#include "Management.h"
#include "HandleRequest.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <errno.h>
Msg msg;

//线程1处理函数
void *Process1(void *arg)
{
    printf("This is Process1!\n");
    HandleRequest(arg);
}

int main()
{
    int ret = -1;
    int sockfd = -1;   //定义socket网络文件描述符
    int clientfd = -1; //定义accept网络文件描述符
    pthread_t th = -1; //定义一个多线程的创建句柄

    struct sockaddr_in servaddr = {0};//服务器对应套接字地址
    struct sockaddr_in cletaddr = {0};//客户端
    socklen_t address_len = 0;        //客户端长度
    unsigned int addrlen = sizeof(struct sockaddr_in);

    //套接字
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd < 0)
    {
        perror("create socket error!\n");
        exit(1);
    }


    memset(&servaddr,0,sizeof(addrlen));
    servaddr.sin_family = AF_INET;//定义servaddr地址组IPv4
    servaddr.sin_port = htons(PORT);//设置监听端口
    servaddr.sin_addr.s_addr = inet_addr(ADDRESS);//定义sercaddr的address
    //servaddr.sin_addr.s_addr = INADDR_ANY;监听主机所有IP

    //由TCP套接字状态TIME_WAIT引起在结束本次会话后close立刻开启下次会话会Bind失败。
	//该状态在套接字关闭后约保留 2 到 4 分钟。在 TIME_WAIT 状态退出之后,套接字被删除,该地址才能被重新绑定而不出问题。
	//因此下面两句话的加入可以解决这个问题
    int opt = 1;
    ret = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

    ret = bind(sockfd,(const struct sockaddr *)&servaddr,sizeof(servaddr));
    if (ret < 0)
    {
        perror("Bind error!\n");
        exit(1);
    }

    ret = listen(sockfd,BACKLOG);
    if (ret < 0)
    {
        perror("Listen error!\n");
        exit(1);
    }
    printf("等待客户端连接......\n");

    memset(&cletaddr,0,addrlen);
    while (1)
    {
        //accept阻塞等待客户端连接
        clientfd = accept(sockfd,(struct sockaddr *)&cletaddr,&addrlen);
        if (clientfd < 0)
        {
            perror("Accept error!\n");
            exit(1);
        }
        printf("listen client success!clientfd=%d\n",clientfd);
        printf("client port=%d\n",ntohs(cletaddr.sin_port));
        printf("client IP=%s\n",inet_ntoa(cletaddr.sin_addr));

        if (pthread_create(&th,NULL,Process1,&clientfd) == -1)
        {
            perror("pthread_create error!\n");
            exit(1);
        }
    }
    return 0;
}

11、Makefile

同样加入了GDB调试参数。

OBJ = List.o FileManagement.o Management.o Socket.o HandleRequest.o

server:$(OBJ)
	gcc -g -o server $(OBJ) -lpthread

List.o:List.c List.h
	gcc -c List.c

FileManagement.o:FileManagement.c FileManagement.h
	gcc -c FileManagement.c

Management.o:Management.c Management.h
	gcc -c Management.c

Socket.o:Socket.c Socket.h
	gcc -c Socket.c

HandleRequest.o:HandleRequest.c HandleRequest.h
	gcc -c HandleRequest.c

.PHONY:clean
clean:
	rm server $(OBJ)

二、Client端

1、Socket.h

#ifndef SOCKET_H
#define SOCKET_H

//#define TO_FILE "/home/liuyin/test/project/test/server/list.data"
#define MSG_MAX 100

#define PORT 8000
#define ADDRESS "192.168.226.128"
//#define ADDRESS "172.30.51.44"
//#define ADDRESS "172.30.50.255"

#define BACKLOG 100
#define MAXLINE 1024

enum MsgType//Client端active的枚举
{
    ADD_INFO = 1,
    UPDATE_INFO,
    DELETE_INFO,
    FIND_NAME,
    FIND_NUM,
    FIND_AGE,
    SORT_NUM,
    SORT_AGE,
    TRAVEL,
    DESTROY
};

typedef struct
{
    int count;
    char type;//消息类型
    char data[100];//消息内容
    char num[20];    //work number
    char name[20];   //name
    char sex[20];    //sex
    char age[20];    //age
    char tel[20];  //phone
}Msg;

#endif

2、Request.h

Client端定义的函数接口。

#ifndef REQUEST_H
#define REQUEST_H

#include "/home/liuyin/test/server/Socket.h"

static void Read_Msg_File(Msg msg);

//目录界面
void Send_ClientMenu(void *arg);
void Recv_ClientMenu(int serverfd);

//新增员工信息
void Add_Info(int serverfd,Msg *msg);

//修改员工信息
void Change_Info(int serverfd,Msg *msg);

//删除员工信息
void Del_Info(int serverfd,Msg *msg);

//按姓名查找
void Find_Name(int serverfd,Msg *msg);

//按工号查找
void Find_Num(int serverfd,Msg *msg);

//按年龄查找
void Find_Age(int serverfd,Msg *msg);

//按工号排序
void Sort_Num(int serverfd,Msg *msg,int Istravel);

//按年龄排序
void Sort_Age(int serverfd,Msg *msg);

//遍历员工信息
void Travel_Info(int serverfd,Msg *msg);

//清空员工信息
void Destroy_Info(int serverfd,Msg *msg);

#endif

3、Client(Client端的main函数)

#include "Request.h"
#include "help.h"
#include <stdio.h>
#include <string.h>

//更新员工信息
static void UpdateInfo(int serverfd,Msg *msg)
{
    int choice = 0;
    while (1)
    {
        printf("=============更新员工信息============\n");
        printf("=           1.新增员工信息          =\n");
        printf("=           2.修改员工信息          =\n");
        printf("=           3.删除员工信息          =\n");
        printf("=           4.  帮助信息            =\n");
        printf("=           0.返回主菜单            =\n");
        printf("=============更新员工信息============\n");
        printf("请选择:");
        scanf("%d",&choice);
        if (0 == choice)
        {
            break;
        }
        switch (choice)
        {
            case 1:
                Add_Info(serverfd,msg);
                Sort_Num(serverfd,msg,0);
            break;
            case 2:
                Change_Info(serverfd,msg);
            break;
            case 3:
                Del_Info(serverfd,msg);
            break;
            case 4:
                help(2);
            break;
            default:
                printf("输入错误!\n");
        }
    } 
}

//查询员工信息
static void FindInfo(int serverfd,Msg *msg)
{

    int choice = 0;
    while (1)
    {
        printf("==============查询员工信息==========\n");
        printf("=           1.按姓名查找           =\n");
        printf("=           2.按工号查找           =\n");
        printf("=           3.按年龄查找           =\n");
        printf("=           4. 帮助信息            =\n");
        printf("=           0.返回主菜单           =\n");
        printf("==============查询员工信息==========\n");
        printf("请选择:");
        scanf("%d",&choice);
        if (0 == choice)
        {
            break;
        }
        switch (choice)
        {
            case 1:
                Find_Name(serverfd,msg);
            break;
            case 2:
                Find_Num(serverfd,msg);
            break;
            case 3:
                Find_Age(serverfd,msg);
            break;
            case 4:
                help(3);
            break;
            default:
                printf("输入错误!\n");
        }
    } 
}

//员工信息排序
static void SortInfo(int serverfd,Msg *msg)
{
    int choice = 0;
    while (1)
    {
        printf("===============员工信息排序==========\n");
        printf("=            1.按工号排序           =\n");
        printf("=            2.按年龄排序           =\n");
        printf("=            3. 帮助信息            =\n");
        printf("=            0. 返回主菜单          =\n");
        printf("===============员工信息排序==========\n");
        printf("请选择:");
        scanf("%d",&choice);
        if (0 == choice)
        {
            break;
        }
        switch (choice)
        {
            case 1:
                Sort_Num(serverfd,msg,1);
            break;
            case 2:
                Sort_Age(serverfd,msg);
            break;
            case 3:
                help(4);
            break;
            default:
                printf("输入错误!\n");
        }
    } 
}

void Send_ClientMenu(void *arg)
{
    unsigned int serverfd = *(unsigned int*)arg;
    Msg msg[MSG_MAX];
    while (1)
    {
        int choice = 0;
        printf("===============主菜单===============\n");
        printf("=         1.更新员工信息            =\n");
        printf("=         2.查询员工信息            =\n");
        printf("=         3.排序员工信息            =\n");
        printf("=         4.遍历员工信息            =\n");
        printf("=         5.清空员工信息            =\n");
        printf("=         6.  帮助信息              =\n");
        printf("=         0.    退出                =\n");
        printf("===============主菜单===============\n");

        printf("请选择想要的操作序号:");
        scanf("%d",&choice);

        if (0 == choice)
        {
            printf("欢迎下次使用!\n");
            break;
        }
        switch (choice)
        {
            case 1:
                UpdateInfo(serverfd,msg);
            break;
            case 2:
                FindInfo(serverfd,msg);
            break;
            case 3:
                SortInfo(serverfd,msg);
            break;
            case 4:
                Travel_Info(serverfd,msg);
            break;
            case 5:
                Destroy_Info(serverfd,msg);
            break;
            case 6:
                help(1);
            break;
            default:
                printf("输入错误!\n");
        }  
    }
}

4、help.h

其实这个帮助信息我也不知道怎么写,只能写一个最笨的也是最简单的帮助信息了,虽然没什么用。

#ifndef HELP_H
#define HELP_H

void help(int n);

#endif

5、help.c

#include "help.h"
#include <stdio.h>

void help(int n)
{
    switch (n)
    {
        case 1:
            printf("1 --进入更新菜单,可以新增、修改和删除员工信息\n");
            printf("2 --进入查询菜单,可以按姓名、工号查找,按年龄范围查找\n");
            printf("3 --进入排序菜单,可以按工号和年龄排序\n");
            printf("4 --显示所有的员工信息\n");
            printf("5 --清空所有员工信息\n");
            printf("6 --显示帮助信息\n");
            printf("0 --退出系统\n");
        break;
        case 2:
            printf("1 --增加新的员工信息,按提示输入员工信息,按0返回\n");
            printf("2 --修改员工信息,输入需要修改的员工工号,若有,则按提示输入新的信息\n");
            printf("3 --删除员工信息,输入想要删除的员工工号,若有则显示删除成功\n");
            printf("4 --显示帮助信息\n");
            printf("0 --返回主菜单\n");
        break;
        case 3:
            printf("1 --按要求输入姓名,有则返回该员工信息(可能不止一名员工)\n");
            printf("2 --按要求输入工号,有则返回该员工信息\n");
            printf("3 --按要求输入年龄界限,选择大于此界限还是小于此界限,返回范围内的员工信息\n");
            printf("4 --显示帮助信息\n");
            printf("0 --返回主菜单\n");
        break;
        case 4:
            printf("1 --按员工工号进行升序排序\n");
            printf("2 --按员工年龄进行升序排序\n");
            printf("3 --显示帮助信息\n");
            printf("0 --返回主菜单\n");
        break;
    }
}

6、Socket.c

#include "Request.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#include<errno.h>
#include <unistd.h>

void *Client_fun1(void *arg)
{
    printf("This is Client_fun1!\n");
    Send_ClientMenu(arg);
}

// void *Client_fun2(void *arg)
// {
//     printf("This is Client_fun2!\n");
//     void Recv_ClientMenu(int serverfd);
// }

int main()
{
    struct sockaddr_in servaddr;
    unsigned int addrlen = sizeof(struct sockaddr_in);
    int sockfd = -1;
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    if (sockfd == -1)
    {
        perror("Client create sockfd error!\n");
        exit(1);
    }
    memset(&servaddr,0,addrlen);
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(PORT);
    servaddr.sin_addr.s_addr = inet_addr(ADDRESS);

    if (connect(sockfd,(struct sockaddr *)&servaddr,addrlen) == -1)
    {
        perror("Client bind error!\n");
        exit(1);
    }
    pthread_t pid1;
    if (pthread_create(&pid1,NULL,Client_fun1,&sockfd) == -1)
    {
        perror("Client pthread_create1 error!\n");
        exit(1);
    }

    // if (pthread_create(&pid2,NULL,Client_fun2,&sockfd) == -1)
    // {
    //     perror("Client pthread_create2 error!\n");
    //     exit(1);
    // }

    pthread_join(pid1,NULL);
    //pthread_join(pid2,NULL);

    return 0;
}

7、Request.c

#include "Request.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static int inputmsg(char *msg)
{
    int n = strcmp(msg,"0");
    return n;
}

//新增员工信息
void Add_Info(int serverfd,Msg *msg)
{
    while (1)
    {
        msg[0].type = ADD_INFO;
        printf("提示:输入0返回更新员工信息菜单!\n");
        printf("请输入员工工号:\n");
        scanf("%s",msg[0].num);
        if (0 == inputmsg(msg[0].num))
        {
            break;
        }
        printf("请输入员工姓名:\n");
        scanf("%s",msg[0].name);
        if ( 0 == inputmsg(msg[0].name))
        {
            break;
        }
        printf("请输入员工性别:\n");
        scanf("%s",msg[0].sex);
        if ( 0 == inputmsg(msg[0].sex))
        {
            break;
        }
        printf("请输入员工年龄:\n");
        scanf("%s",msg[0].age);
        if ( 0 == inputmsg(msg[0].age))
        {
            break;
        }
        printf("请输入员工电话:\n");
        scanf("%s",msg[0].tel);
        if ( 0 == inputmsg(msg[0].tel))
        {
            break;
        }

        write(serverfd,msg,sizeof(Msg));
        memset(msg,0,sizeof(Msg));
        read(serverfd,msg,sizeof(Msg));
        if (0 == inputmsg(msg[0].num))
        {
            printf("%s\n",msg[0].data);
        }
        else
        {
            printf("%s\n",msg[0].data);
        }
    }
}

//修改员工信息
void Change_Info(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = UPDATE_INFO;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要修改的员工工号:");
    scanf("%s",msg[0].num);
    if (0 == inputmsg(msg[0].num))
    {
        return;
    }
    //printf("%s\n",msg[0].num);
    write(serverfd,msg,sizeof(Msg));
    memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg));
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        printf("%s\n",msg[0].data);
        printf("\n工号    姓名    性别    年龄    电话\n");
        printf("\n %s\t %s\t %s\t %s\t %s\t\n",msg[0].num,msg[0].name,msg[0].sex,msg[0].age,msg[0].tel);
        memset(msg,0,sizeof(Msg));
        printf("请输入新工号:");
        scanf("%s",msg[0].num);
        printf("请输入新姓名:");
        scanf("%s",msg[0].name);
        printf("请输入新性别:");
        scanf("%s",msg[0].sex);
        printf("请输入新年龄:");
        scanf("%s",msg[0].age);
        printf("请输入新电话:");
        scanf("%s",msg[0].tel);
        write(serverfd,msg,sizeof(Msg));
        printf("员工信息修改成功!\n");
    }
}

//删除员工信息
void Del_Info(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = DELETE_INFO;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要删除的员工工号:");
    scanf("%s",msg[0].num);
    if (0 == inputmsg(msg[0].num))
    {
        return;
    }
    write(serverfd,msg,sizeof(Msg));
    memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg));
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        printf("删除成功!\n");
    }

}

//按姓名查找
void Find_Name(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = FIND_NAME;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要查找的员工姓名:");
    scanf("%s",msg[0].name);
    if (0 == inputmsg(msg[0].name))
    {
        return;
    }
    write(serverfd,msg,sizeof(Msg));
    memset(msg,0,sizeof(Msg));
    int n = read(serverfd,msg,sizeof(Msg[MSG_MAX]));
    //printf("msg[0].count=%d\n",msg[0].count);
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        printf("\n工号    姓名    性别    年龄    电话\n");
        int i = 1;
        for (;i <= msg[0].count;i++)
        {
            printf("\n %s\t %s\t %s\t %s\t %s\t\n",msg[i].num,msg[i].name,msg[i].sex,msg[i].age,msg[i].tel);
        }
    }
}

//按工号查找
void Find_Num(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = FIND_NUM;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入你要查找的员工工号:");
    scanf("%s",msg[0].num);
    if (0 == inputmsg(msg[0].num))
    {
        return;
    }
    write(serverfd,msg,sizeof(Msg));
    //printf("%s\n",msg.num);
    memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg));

    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    printf("%s\n",msg[0].data);
    printf("\n工号    姓名    性别    年龄    电话\n");
    printf("\n %s\t %s\t %s\t %s\t %s\t\n",msg[0].num,msg[0].name,msg[0].sex,msg[0].age,msg[0].tel);
}

//按年龄查找
void Find_Age(int serverfd,Msg *msg)
{
    int n = 0;
    memset(msg,0,sizeof(Msg));
    msg[0].type = FIND_AGE;
    printf("提示:输入0返回更新员工信息菜单!\n");
    printf("请输入年龄界限:");
    scanf("%s",msg[0].age);
    if (0 == inputmsg(msg[0].age))
    {
        return;
    }
    printf("请选择大于或小于此年龄:1-小于  2-大于 0-退出:");
    scanf("%d",&n);
    switch (n)
    {
        case 1:
            strcpy(msg[0].data,"1");
            break;
        case 2:
            strcpy(msg[0].data,"2");
            break;
            case 0:
                return;
            break;
        default:
            printf("输入错误!\n");
    }
    write(serverfd,msg,sizeof(Msg));
    memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg[MSG_MAX]));
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        printf("%s\n",msg[0].data);
        printf("\n工号    姓名    性别    年龄    电话\n");
        
        int i = 1;
        for (;i <= msg[0].count;i++)
        {
            printf("\n %s\t %s\t %s\t %s\t %s\t\n",msg[i].num,msg[i].name,msg[i].sex,msg[i].age,msg[i].tel);
        }
    }
}

//按工号排序
void Sort_Num(int serverfd,Msg *msg,int Istravel)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = SORT_NUM;
    write(serverfd,msg,sizeof(Msg));
    memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg));
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        if (Istravel)
        {
            Travel_Info(serverfd,msg);
        }
    }
}

//按年龄排序
void Sort_Age(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = SORT_AGE;
    write(serverfd,msg,sizeof(Msg));
    memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg));
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        Travel_Info(serverfd,msg);
    }
}

//遍历员工信息
void Travel_Info(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg[MSG_MAX]));
    msg[0].type = TRAVEL;
    write(serverfd,msg,sizeof(Msg));
    //memset(msg,0,sizeof(Msg[MSG_MAX]));
    read(serverfd,msg,sizeof(Msg[MSG_MAX]));
    if (0 == inputmsg(msg[0].num))
    {
        printf("%s\n",msg[0].data);
        return;
    }
    else
    {
        printf("%s\n",msg[0].data);
        printf("\n工号    姓名    性别    年龄    电话\n");
        int i = 0;
        for (;i <= msg[0].count;i++)
        {
            printf("\n %s\t %s\t %s\t %s\t %s\t\n",msg[i].num,msg[i].name,msg[i].sex,msg[i].age,msg[i].tel);
        }
    }
}

//清空员工信息
void Destroy_Info(int serverfd,Msg *msg)
{
    memset(msg,0,sizeof(Msg));
    msg[0].type = DESTROY;
    write(serverfd,msg,sizeof(Msg));
    //memset(msg,0,sizeof(Msg));
    read(serverfd,msg,sizeof(Msg[MSG_MAX]));
    printf("%s\n",msg[0].data);
}



8、Makefile

同样加入了GDB调试参数。

OBJ = Socket.o Client.o Request.o help.o

client:$(OBJ)
	gcc -g -o client $(OBJ) -lpthread

Client.o:Client.c Request.h
	gcc -c Client.c

Socket.o:Socket.c Socket.h
	gcc -c Socket.c

Request.o:Request.c Request.h
	gcc -c Request.c

help.o:help.c help.h
	gcc -c help.c

.PHONY:clean
clean:
	rm client $(OBJ)

四、总结

以上就是员工管理系统的全部代码,有很多地方写的不好,但是作为学习的阶段性成果,还是很有纪念意义的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值