网络编程实现一个C/S模式的员工管理系统

通过网络编程实现一个C/S模式的员工管理系统,服务器端用多进程或多线程模型支持多个客户端同时连接、操作。具体要求如下:

(1)员工信息包括三个字段:姓名,年龄,手机号,用结构体表示;
(2)服务器功能:
添加新员工——接受客户端发送来的新员工结构体数据,追加到数据文件emp.db中;
获取员工列表——把emp.db中的每个员工结构体数据读出发回客户端;
(3)客户端功能:
添加新员工——从终端读取新员工信息并构造为结构体变量,发到服务器请求添加新员工;
显示员工列表——向服务器请求员工列表,接收后显示到终端。
(4)客户端和服务器之间的协议应事先设计,如服务器返回给客户端的各类报告信息、错误信息都应事先统一设计好编号,类似真正DBMS那样。

客户端

#include 
#include 
#include 
#include 
#include 
#include 

#define SERVER_IP "127.0.0.1"
#define PORT 8888

typedef struct {
    char name[20];
    int age;
    char phone[12];
} Employee;


typedef struct {
    int type; 
    Employee employee; 
} Message;

// 打印菜单选项
void print_menu() {
    printf("1. 添加新员工\n");
    printf("2. 显示员工列表\n");
    printf("0. 退出\n");
}

// 添加新员工函数
void add_employee(int server_fd) {
    Employee employee;
    printf("请输入员工姓名:");
    scanf("%s", employee.name);
    printf("请输入员工年龄:");
    scanf("%d", &employee.age);
    printf("请输入员工手机号:");
    scanf("%s", employee.phone);


    Message msg = {
        .type = 1,
        .employee = employee
    };
    send(server_fd, &msg, sizeof(msg), 0);
    printf("添加成功!\n");
}


void show_employee_list(int server_fd) {
 
    Message msg = {
        .type = 2
    };
    send(server_fd, &msg, sizeof(msg), 0);

    while (1) {
        Message msg;
        recv(server_fd, &msg, sizeof(msg), 0);
        if (msg.type == 3) { // 单个员工信息
            printf("%s\t%d\t%s\n", msg.employee.name, msg.employee.age, msg.employee.phone);
        } else if (msg.type == 4) { // 员工信息接收结束
            break;
        }
    }
}

int main() {

    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket");
        exit(1); 
    }

    // 配置服务器地址信息
    struct sockaddr_in server_addr = {
        .sin_family = AF_INET, // IPv4 地址族
        .sin_port = htons(PORT), // 指定端口号
        .sin_addr.s_addr = inet_addr(SERVER_IP) // 指定服务器 IP 地址
    };

    // 连接服务器
    if (connect(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("connect");
        exit(1);
    }

    printf("连接服务器成功!\n");

    // 进入菜单循环,等待用户输入操作选项
    while (1) {
        print_menu();
        int choice;
        printf("请选择:");
        scanf("%d", &choice);
        switch (choice) {
            case 1:
                add_employee(server_fd); // 添加新员工
                break;
            case 2:
                show_employee_list(server_fd); // 显示员工列表
                break;
            case 0:
                close(server_fd); // 关闭套接字,退出程序
                return 0;
            default:
                printf("无效选择!\n"); // 输入无效选项时提示用户
                break;
        }
    }

    return 0; 
}

服务端

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 8888
#define MAX_CLIENTS 10
#define MAX_EMPLOYEES 100

typedef struct {
    char name[20];
    int age;
    char phone[12];
} Employee;

typedef struct {
    int type;
    Employee employee;
    size_t len;
} Message;

Employee employees[MAX_EMPLOYEES];
int num_employees = 0;

void *handle_client(void *arg) {
    int client_fd = *(int *)arg;
    Message msg;
    while (recv(client_fd, &msg, sizeof(msg), 0) > 0) {
        switch (msg.type) {
            case 1: // 添加新员工
                employees[num_employees++] = msg.employee;
                FILE *fp = fopen("emp.db", "ab");
                if (fp == NULL) {
                    perror("fopen");
                    exit(1);
                }
                fwrite(&msg.employee, sizeof(Employee), 1, fp);
                fclose(fp);
                break;
            case 2: // 获取员工列表
                for (int i = 0; i < num_employees; i++) {
                    msg.type = 3; // 员工信息
                    msg.employee = employees[i];
                    msg.len = sizeof(Employee);
                    send(client_fd, &msg, sizeof(msg), 0);
                }
                msg.type = 4; // 结束标志
                msg.len = 0;
                send(client_fd, &msg, sizeof(msg), 0);
                break;
            default:
                break;
        }
    }
    close(client_fd);
    return NULL;
}

int main() {
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd < 0) {
        perror("socket");
        exit(1);
    }
    struct sockaddr_in server_addr = {
        .sin_family = AF_INET,
        .sin_port = htons(PORT),
        .sin_addr.s_addr = INADDR_ANY
    };
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        perror("bind");
        exit(1);
    }
    if (listen(server_fd, MAX_CLIENTS) < 0) {
        perror("listen");
        exit(1);
    }
    printf("服务开启 %d\n", PORT);
    pthread_t tid;
    pthread_attr_t attr;
    pthread_attr_init(&attr);
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    FILE *fp = fopen("emp.db", "rb");
    if (fp == NULL) {
        perror("fopen");
        exit(1);
    }
    while (fread(&employees[num_employees], sizeof(Employee), 1,fp) > 0) {
        num_employees++;
        if (num_employees >= MAX_EMPLOYEES) {
            break;
        }
    }
    fclose(fp);
    while (1) {
        struct sockaddr_in client_addr;
        socklen_t client_len = sizeof(client_addr);
        int client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
        if (client_fd < 0) {
            perror("accept");
            continue;
        }
        pthread_create(&tid, &attr, handle_client, &client_fd);
    }
    pthread_attr_destroy(&attr);
    return 0;
}

你可能感兴趣的:(linux编程,网络,c语言,开发语言)