通过网络编程实现一个C/S模式的员工管理系统,服务器端用多进程或多线程模型支持多个客户端同时连接、操作。具体要求如下: (1)员工信息包括三个字段:姓名,年龄,手机号,用结构体表示;
时间: 2023-05-25 07:02:41 浏览: 146
(2)支持添加员工、删除员工、查看所有员工信息、按照年龄排序查看员工信息等操作;
(3)服务器端和客户端之间通过套接字进行通信,服务器接收客户端请求并处理,返回相应的结果;
(4)服务器端需要支持多个客户端的同时连接和操作;
(5)服务器端采用多进程或多线程模型均可。
下面是一个示例的服务器端代码实现:
```c++
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <vector>
#include <algorithm>
using namespace std;
// 员工信息结构体
struct Employee {
string name;
int age;
string phone;
Employee(string n = "", int a = 0, string p = "") {
name = n;
age = a;
phone = p;
}
};
// 员工信息数据
vector<Employee> employees;
// 线程处理函数
void *handle_client(void *client_socket_ptr) {
// 取出客户端socket
int client_socket = *((int *) client_socket_ptr);
while (true) {
// 接收客户端数据
char buffer[1024];
int recv_len = recv(client_socket, buffer, sizeof(buffer), 0);
if (recv_len <= 0) {
// 接收失败或客户端关闭连接,退出线程
break;
}
buffer[recv_len] = '\0'; // 保证字符串以'\0'结尾
// 解析客户端数据
string request(buffer);
// 处理客户端请求
string response;
if (request == "quit") {
// 客户端请求退出
response = "BYE";
break;
} else if (request == "list") {
// 客户端请求列出所有员工信息
response = "NAME\tAGE\tPHONE\n";
for (auto e : employees) {
response += e.name + "\t" + to_string(e.age) + "\t" + e.phone + "\n";
}
} else if (request == "add") {
// 客户端请求添加员工信息
char name[256], phone[256];
int age;
sscanf(buffer, "add %s %d %s", name, &age, phone);
employees.emplace_back(name, age, phone);
response = "OK";
} else if (request == "rm") {
// 客户端请求删除某个员工信息
char name[256];
sscanf(buffer, "rm %s", name);
auto it = find_if(employees.begin(), employees.end(), [&](Employee e) {
return e.name == name;
});
if (it != employees.end()) {
employees.erase(it);
response = "OK";
} else {
response = "NOT FOUND";
}
} else if (request == "age") {
// 客户端请求按照年龄排序显示员工信息
sort(employees.begin(), employees.end(), [&](Employee a, Employee b) {
return a.age < b.age;
});
response = "NAME\tAGE\tPHONE\n";
for (auto e : employees) {
response += e.name + "\t" + to_string(e.age) + "\t" + e.phone + "\n";
}
} else {
// 客户端请求不合法
response = "INVALID COMMAND";
}
// 发送响应给客户端
send(client_socket, response.c_str(), response.size(), 0);
}
// 关闭客户端socket
close(client_socket);
// 释放客户端socket堆空间
delete (int *) client_socket_ptr;
// 线程退出
return nullptr;
}
int main(int argc, char *argv[]) {
// 创建服务器socket
int server_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (server_socket < 0) {
cerr << "ERROR: Failed to create server socket." << endl;
return 1;
}
// 绑定服务器地址和端口号
struct sockaddr_in server_addr{};
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(12345);
if (bind(server_socket, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0) {
cerr << "ERROR: Failed to bind server address." << endl;
close(server_socket);
return 1;
}
// 开始监听客户端连接
if (listen(server_socket, 10) < 0) {
cerr << "ERROR: Failed to listen on server socket." << endl;
close(server_socket);
return 1;
}
// 主线程等待客户端连接并创建线程处理客户端请求
pthread_t tid;
while (true) {
// 等待客户端连接
struct sockaddr_in client_addr{};
socklen_t client_addr_len = sizeof(client_addr);
int client_socket = accept(server_socket, (struct sockaddr *) &client_addr, &client_addr_len);
if (client_socket < 0) {
cerr << "ERROR: Failed to accept client connection." << endl;
continue;
}
// 创建线程处理客户端请求
int *client_socket_ptr = new int(client_socket); // 需要堆上分配空间,以便在线程函数内部释放
int rc = pthread_create(&tid, nullptr, handle_client, (void *) client_socket_ptr);
if (rc != 0) {
cerr << "ERROR: Failed to create client thread." << endl;
close(client_socket);
delete client_socket_ptr;
continue;
}
// 线程分离
pthread_detach(tid);
}
// 关闭服务器socket
close(server_socket);
return 0;
}
```
其中,主线程不断地等待客户端连接并创建线程处理客户端请求,每个线程函数中实现具体的员工管理操作:收到客户端请求后进行解析,然后调用相应的函数进行处理,并将处理结果发送回客户端。实现方式比较简单,使用了C++标准库中的vector、algorithm等容器和算法处理员工信息,使用了线程库pthread实现了多线程模型。在main函数中并未指定多进程或多线程模型,可以根据实际需要选择。
阅读全文