#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <pthread.h>
#define BUFFER_SIZE 1024
#define EXIT_MESSAGE "exit"
#define THREAD_POOL_SIZE 5 // 线程池中的工作线程数量
typedef struct {
int client_socket;
int id;
} Task;
typedef struct {
Task* task_queue;
int front;
int rear;
int size;
int capacity;
pthread_mutex_t mutex;
pthread_cond_t full;
pthread_cond_t empty;
} ThreadPool;
ThreadPool thread_pool;
int busy_threads = 0;
int active_threads = 0;
int client_count = 1;
void error(const char *message) {
perror(message);
exit(1);
}
void initThreadPool(int capacity) {
thread_pool.task_queue = (Task*)malloc(sizeof(Task) * capacity);
thread_pool.front = 0;
thread_pool.rear = -1;
thread_pool.size = 0;
thread_pool.capacity = capacity;
pthread_mutex_init(&thread_pool.mutex, NULL);
pthread_cond_init(&thread_pool.full, NULL);
pthread_cond_init(&thread_pool.empty, NULL);
}
void destroyThreadPool() {
free(thread_pool.task_queue);
pthread_mutex_destroy(&thread_pool.mutex);
pthread_cond_destroy(&thread_pool.full);
pthread_cond_destroy(&thread_pool.empty);
}
void enqueue(Task task) {
pthread_mutex_lock(&thread_pool.mutex);
while (thread_pool.size >= thread_pool.capacity) {
pthread_cond_wait(&thread_pool.full, &thread_pool.mutex);
}
thread_pool.rear = (thread_pool.rear + 1) % thread_pool.capacity;
thread_pool.task_queue[thread_pool.rear] = task;
thread_pool.size++;
pthread_cond_signal(&thread_pool.empty);
pthread_mutex_unlock(&thread_pool.mutex);
}
Task dequeue() {
Task task;
pthread_mutex_lock(&thread_pool.mutex);
while (thread_pool.size <= 0) {
pthread_cond_wait(&thread_pool.empty, &thread_pool.mutex);
}
task = thread_pool.task_queue[thread_pool.front];
thread_pool.front = (thread_pool.front + 1) % thread_pool.capacity;
thread_pool.size--;
pthread_cond_signal(&thread_pool.full);
pthread_mutex_unlock(&thread_pool.mutex);
return task;
}
void* workerThread(void* arg) {
int id = *(int*)arg;
free(arg);
while (1) {
Task task = dequeue();
if (task.client_socket < 0) {
break; // 遇到特殊任务时终止线程
}
printf("客户端 %d 连接成功 (线程 %d)\n", task.id, id);
// 处理客户端请求
char buffer[BUFFER_SIZE];
memset(buffer, 0, sizeof(buffer));
while (1) {
// 接收客户端消息
if (recv(task.client_socket, buffer, sizeof(buffer), 0) < 0) {
error("接收数据时出错");
}
printf("客户端 %d (线程 %d): %s\n", task.id, id, buffer);
// 去除换行符
buffer[strcspn(buffer, "\n")] = '\0';
// 检查退出消息
if (strcmp(buffer, EXIT_MESSAGE) == 0) {
printf("客户端 %d (线程 %d) 退出\n", task.id, id);
break;
}
// 发送消息给客户端
printf("服务器 (线程 %d): ", id);
fgets(buffer, sizeof(buffer), stdin);
// 去除换行符
buffer[strcspn(buffer, "\n")] = '\0';
// 检查退出消息
if (strcmp(buffer, EXIT_MESSAGE) == 0) {
if (send(task.client_socket, buffer, strlen(buffer), 0) < 0) {
error("发送数据时出错");
}
printf("您已退出\n");
break;
}
if (send(task.client_socket, buffer, strlen(buffer), 0) < 0) {
error("发送数据时出错");
}
memset(buffer, 0, sizeof(buffer));
}
// 关闭客户端套接字
close(task.client_socket);
busy_threads--;
}
pthread_exit(NULL);
}
void* managerThread(void* arg) {
while (1) {
sleep(5); // 每5秒检查一次任务队列
pthread_mutex_lock(&thread_pool.mutex);
int tasks = thread_pool.size;
int workers = active_threads - busy_threads;
printf("任务数:%d,工作线程数:%d\n", tasks, workers);
if (tasks > workers && active_threads < thread_pool.capacity) {
int* new_thread_id = (int*)malloc(sizeof(int));
*new_thread_id = active_threads + 1;
pthread_t new_thread;
pthread_create(&new_thread, NULL, workerThread, (void*)new_thread_id);
pthread_detach(new_thread);
active_threads++;
}
if (tasks < workers && active_threads > 1) {
enqueue((Task){-1, -1}); // 添加一个特殊任务来终止多余的线程
active_threads--;
}
pthread_mutex_unlock(&thread_pool.mutex);
}
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "用法:%s <端口号>\n", argv[0]);
exit(1);
}
int server_socket, client_socket;
char buffer[BUFFER_SIZE];
struct sockaddr_in server_addr, client_addr;
socklen_t client_addr_len;
// 创建服务器套接字
server_socket = socket(AF_INET, SOCK_STREAM, 0);
if (server_socket < 0) {
error("打开套接字时出错");
}
// 设置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(atoi(argv[1]));
// 将服务器套接字绑定到指定端口
if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
error("绑定套接字时出错");
}
// 监听连接请求
if (listen(server_socket, 5) < 0) {
error("监听时出错");
}
printf("等待连接...\n");
initThreadPool(THREAD_POOL_SIZE);
// 创建管理者线程
pthread_t manager_thread;
pthread_create(&manager_thread, NULL, managerThread, NULL);
while (1) {
// 接受客户端连接
client_addr_len = sizeof(client_addr);
client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_socket < 0) {
error("接受连接时出错");
}
// 将客户端任务加入队列
Task task = {client_socket, client_count};
enqueue(task);
busy_threads++;
client_count++;
}
// 关闭服务器套接字
close(server_socket);
// 等待管理者线程结束
pthread_join(manager_thread, NULL);
destroyThreadPool();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define BUFFER_SIZE 1024
#define EXIT_MESSAGE "exit"
void error(const char *message) {
perror(message);
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "用法:%s <服务器IP> <服务器端口>\n", argv[0]);
exit(1);
}
int client_socket;
char buffer[BUFFER_SIZE];
struct sockaddr_in server_addr;
// 创建客户端套接字
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket < 0) {
error("打开套接字时出错");
}
// 设置服务器地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(argv[1]);
server_addr.sin_port = htons(atoi(argv[2]));
// 连接到服务器
if (connect(client_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
error("连接服务器时出错");
}
printf("连接到服务器\n");
// 发送和接收消息,直到发送退出消息
while (1) {
// 发送消息给服务器
printf("客户端:");
fgets(buffer, sizeof(buffer), stdin);
// 去除换行符
buffer[strcspn(buffer, "\n")] = '\0';
// 检查退出消息
if (strcmp(buffer, EXIT_MESSAGE) == 0) {
if (send(client_socket, buffer, strlen(buffer), 0) < 0) {
error("发送数据时出错");
}
printf("您已退出\n");
break;
}
if (send(client_socket, buffer, strlen(buffer), 0) < 0) {
error("发送数据时出错");
}
// 接收服务器消息
memset(buffer, 0, sizeof(buffer));
if (recv(client_socket, buffer, sizeof(buffer), 0) < 0) {
error("接收数据时出错");
}
printf("服务器:%s\n", buffer);
}
// 关闭套接字
close(client_socket);
return 0;
}