838383

#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"

typedef struct {

    int client_socket;

    int id;

} ClientInfo;

typedef struct {

    ClientInfo *client_info;

    int size;

    int capacity;

    pthread_mutex_t lock;

    pthread_cond_t notify;

} ThreadPool;

typedef struct {

    ThreadPool *thread_pool;

    int max_tasks;

    int busy_threads;

} ManagerThreadInfo;

void error(const char *message) {

    perror(message);

    exit(1);

}

ThreadPool *createThreadPool(int capacity) {

    ThreadPool *thread_pool = (ThreadPool *)malloc(sizeof(ThreadPool));

    thread_pool->client_info = (ClientInfo *)malloc(capacity * sizeof(ClientInfo));

    thread_pool->size = 0;

    thread_pool->capacity = capacity;

    pthread_mutex_init(&thread_pool->lock, NULL);

    pthread_cond_init(&thread_pool->notify, NULL);

    return thread_pool;

}

void destroyThreadPool(ThreadPool *thread_pool) {

    free(thread_pool->client_info);

    pthread_mutex_destroy(&thread_pool->lock);

    pthread_cond_destroy(&thread_pool->notify);

    free(thread_pool);

}

void addToThreadPool(ThreadPool *thread_pool, ClientInfo client_info) {

    pthread_mutex_lock(&thread_pool->lock);

    // 等待直到线程池中有空闲位置

    while (thread_pool->size == thread_pool->capacity) {

        pthread_cond_wait(&thread_pool->notify, &thread_pool->lock);

    }

    // 添加客户端信息到线程池

    thread_pool->client_info[thread_pool->size++] = client_info;

    pthread_cond_signal(&thread_pool->notify); // 通知工作线程有新的任务

    pthread_mutex_unlock(&thread_pool->lock);

}

ClientInfo removeFromThreadPool(ThreadPool *thread_pool) {

    pthread_mutex_lock(&thread_pool->lock);

    // 等待直到线程池中有任务

    while (thread_pool->size == 0) {

        pthread_cond_wait(&thread_pool->notify, &thread_pool->lock);

    }

    // 从线程池中获取客户端信息

    ClientInfo client_info = thread_pool->client_info[--thread_pool->size];

    pthread_cond_signal(&thread_pool->notify); // 通知等待的线程有空闲位置

    pthread_mutex_unlock(&thread_pool->lock);

    return client_info;

}

void *workerThread(void *arg) {

    ClientInfo client_info = *(ClientInfo *)arg;

    int client_socket = client_info.client_socket;

    int client_id = client_info.id;

    char buffer[BUFFER_SIZE];

    // 接收和发送消息,直到收到退出消息

    while (1) {

        // 接收客户端消息

        memset(buffer, 0, sizeof(buffer));

        if (recv(client_socket, buffer, sizeof(buffer), 0) < 0) {

            perror("Error receiving data");

            break;

        }

        printf("Client %d: %s\n", client_id, buffer);

        // 去除换行符

        buffer[strcspn(buffer, "\n")] = '\0';

        // 检查退出消息

        if (strcmp(buffer, EXIT_MESSAGE) == 0) {

            printf("Client %d exited\n", client_id);

            break;

        }

        // 发送消息给客户端

        printf("Server: ");

        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) {

                perror("Error sending data");

                break;

            }

            printf("You exited\n");

            break;

        }

        if (send(client_socket, buffer, strlen(buffer), 0) < 0) {

            perror("Error sending data");

            break;

        }

    }

    // 关闭客户端套接字

    close(client_socket);

    free(arg);  // 释放动态分配的客户端信息内存

    return NULL;

}

void *managerThread(void *arg) {

    ManagerThreadInfo *manager_thread_info = (ManagerThreadInfo *)arg;

    ThreadPool *thread_pool = manager_thread_info->thread_pool;

    int max_tasks = manager_thread_info->max_tasks;

    while (1) {

        sleep(5);  // 每隔5秒检查一次任务数量和忙状态线程个数

        pthread_mutex_lock(&thread_pool->lock);

        int tasks = thread_pool->size;

        int busy_threads = manager_thread_info->busy_threads;

        // 当任务过多且忙状态线程个数不超过任务数时,创建新的工作线程

        if (tasks > max_tasks && busy_threads < tasks) {

            pthread_t thread;

            ClientInfo client_info = removeFromThreadPool(thread_pool);

            manager_thread_info->busy_threads++;

            pthread_create(&thread, NULL, workerThread, (void *)&client_info);

            pthread_detach(thread);

            printf("Created new worker thread\n");

        }

        // 当任务过少且忙状态线程个数超过任务数时,销毁部分工作线程

        else if (tasks < max_tasks && busy_threads > tasks) {

            manager_thread_info->busy_threads--;

            printf("Destroyed a worker thread\n");

        }

        pthread_mutex_unlock(&thread_pool->lock);

    }

    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");

    int client_count = 1;

    ThreadPool *thread_pool = createThreadPool(10);  // 创建线程池,最多容纳10个任务

    ManagerThreadInfo manager_thread_info;

    manager_thread_info.thread_pool = thread_pool;

    manager_thread_info.max_tasks = 5;  // 任务数量超过5时,创建新的工作线程

    manager_thread_info.busy_threads = 0;

    pthread_t manager_thread;

    pthread_create(&manager_thread, NULL, managerThread, (void *)&manager_thread_info);

    while (1) {

        // 接受客户端连接

        client_addr_len = sizeof(client_addr);

        client_socket = accept(server_socket, (struct sockaddr *)&client_addr, &client_addr_len);

        if (client_socket < 0) {

            perror("Error accepting connection");

            continue;

        }

        printf("Client %d connected\n", client_count);

        // 创建客户端信息并添加到线程池

        ClientInfo *client_info = (ClientInfo *)malloc(sizeof(ClientInfo));

        client_info->client_socket = client_socket;

        client_info->id = client_count;

        addToThreadPool(thread_pool, *client_info);

        client_count++;

    }

    // 关闭服务器套接字

    close(server_socket);

    destroyThreadPool(thread_pool);  // 销毁线程池

    pthread_join(manager_thread, NULL);  // 等待管理者线程退出

    return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值