#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 client_id;
} ClientInfo;
typedef struct {
pthread_t *threads;
int thread_count;
ClientInfo **clients;
int client_count;
pthread_mutex_t mutex;
pthread_cond_t condition;
int is_running;
int next_client_id;
} ThreadPool;
void error(const char *message) {
perror(message);
exit(1);
}
void *handle_client(void *arg) {
ClientInfo *client_info = (ClientInfo *)arg;
int client_socket = client_info->client_socket;
int client_id = client_info->client_id;
char buffer[BUFFER_SIZE];
while (1) {
// 接收客户端消息
memset(buffer, 0, sizeof(buffer));
if (recv(client_socket, buffer, sizeof(buffer), 0) < 0) {
error("Error receiving data");
}
printf("Client %d: %s\n", client_id, buffer);
// 去除换行符
buffer[strcspn(buffer, "\n")] = '\0';
// 检查退出消息
if (strcmp(buffer, EXIT_MESSAGE) == 0) {
printf("Client %d disconnected\n", client_id);
break;
}
// 处理客户端请求(这里只是回显)
if (send(client_socket, buffer, strlen(buffer), 0) < 0) {
error("Error sending data");
}
}
// 关闭客户端套接字
close(client_socket);
free(client_info);
pthread_exit(NULL);
}
void *worker_thread(void *arg) {
ThreadPool *thread_pool = (ThreadPool *)arg;
while (1) {
ClientInfo *client_info = NULL;
pthread_mutex_lock(&thread_pool->mutex);
// 等待有可用的任务
while (thread_pool->client_count == 0 && thread_pool->is_running) {
pthread_cond_wait(&thread_pool->condition, &thread_pool->mutex);
}
// 任务队列为空且线程池停止运行,结束线程
if (thread_pool->client_count == 0 && !thread_pool->is_running) {
pthread_mutex_unlock(&thread_pool->mutex);
break;
}
// 获取任务
client_info = thread_pool->clients[--thread_pool->client_count];
pthread_mutex_unlock(&thread_pool->mutex);
// 处理任务
handle_client(client_info);
}
return NULL;
}
void *manager_thread(void *arg) {
ThreadPool *thread_pool = (ThreadPool *)arg;
while (1) {
pthread_mutex_lock(&thread_pool->mutex);
// 检查任务队列长度和工作线程数量
int client_count = thread_pool->client_count;
int thread_count = thread_pool->thread_count;
// 根据任务队列长度和工作线程数量调整线程池
if (client_count > thread_count && thread_count < THREAD_POOL_SIZE) {
// 创建新的工作线程
pthread_t *threads = (pthread_t *)realloc(thread_pool->threads, (thread_count + 1) * sizeof(pthread_t));
if (threads == NULL) {
fprintf(stderr, "Error reallocating memory\n");
break;
}
thread_pool->threads = threads;
thread_pool->thread_count++;
pthread_create(&thread_pool->threads[thread_count], NULL, worker_thread, thread_pool);
} else if (client_count < thread_count && thread_count > 1) {
// 销毁一个工作线程
thread_pool->is_running = 0;
pthread_cond_broadcast(&thread_pool->condition);
pthread_mutex_unlock(&thread_pool->mutex);
for (int i = 0; i < thread_count; i++) {
pthread_join(thread_pool->threads[i], NULL);
}
free(thread_pool->threads);
thread_pool->threads = NULL;
thread_pool->thread_count--;
pthread_mutex_lock(&thread_pool->mutex);
thread_pool->is_running = 1;
}
pthread_mutex_unlock(&thread_pool->mutex);
// 休眠一段时间后重新检查
sleep(1);
}
return NULL;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s <port>\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("Error opening socket");
}
// 设置服务器地址结构
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("Error binding socket");
}
// 监听连接请求
if (listen(server_socket, 5) < 0) {
error("Error listening");
}
printf("Waiting for connections...\n");
ThreadPool thread_pool;
thread_pool.threads = NULL;
thread_pool.thread_count = 0;
thread_pool.clients = (ClientInfo **)malloc(THREAD_POOL_SIZE * sizeof(ClientInfo *));
thread_pool.client_count = 0;
pthread_mutex_init(&thread_pool.mutex, NULL);
pthread_cond_init(&thread_pool.condition, NULL);
thread_pool.is_running = 1;
thread_pool.next_client_id = 1;
// 创建管理者线程
pthread_t manager_thread;
pthread_create(&manager_thread, NULL, manager_thread, &thread_pool);
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("Error accepting connection");
}
printf("Client connected\n");
// 创建客户端信息结构体
ClientInfo *client_info = (ClientInfo *)malloc(sizeof(ClientInfo));
client_info->client_socket = client_socket;
client_info->client_id = thread_pool.next_client_id++;
// 创建线程处理客户端通信
pthread_t thread;
if (pthread_create(&thread, NULL, handle_client, client_info) != 0) {
error("Error creating thread");
}
pthread_mutex_lock(&thread_pool.mutex);
// 将客户端信息添加到任务队列中
if (thread_pool.client_count < THREAD_POOL_SIZE) {
thread_pool.clients[thread_pool.client_count++] = client_info;
pthread_cond_signal(&thread_pool.condition);
} else {
// 线程池已满,拒绝连接
printf("Thread pool is full. Connection rejected.\n");
close(client_socket);
free(client_info);
}
pthread_mutex_unlock(&thread_pool.mutex);
}
// 停止线程池运行
thread_pool.is_running = 0;
pthread_cond_broadcast(&thread_pool.condition);
// 等待管理者线程结束
pthread_join(manager_thread, NULL);
// 等待线程池中的线程结束
for (int i = 0; i < thread_pool.thread_count; i++) {
pthread_join(thread_pool.threads[i], NULL);
}
// 关闭服务器套接字
close(server_socket);
pthread_mutex_destroy(&thread_pool.mutex);
pthread_cond_destroy(&thread_pool.condition);
// 释放内存
for (int i = 0; i < thread_pool.client_count; i++) {
free(thread_pool.clients[i]);
}
free(thread_pool.clients);
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, "Usage: %s <server_ip> <server_port>\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("Error opening socket");
}
// 设置服务器地址结构
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("Error connecting to server");
}
printf("Connected to server\n");
// 发送和接收消息,直到发送退出消息
while (1) {
// 发送消息给服务器
printf("Client: ");
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("Error sending data");
}
printf("You exited\n");
break;
}
if (send(client_socket, buffer, strlen(buffer), 0) < 0) {
error("Error sending data");
}
// 接收服务器消息
memset(buffer, 0, sizeof(buffer));
if (recv(client_socket, buffer, sizeof(buffer), 0) < 0) {
error("Error receiving data");
}
printf("Server: %s\n", buffer);
}
// 关闭套接字
close(client_socket);
return 0;
}