溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

線程池網(wǎng)絡(luò)服務(wù)

發(fā)布時(shí)間:2020-06-21 10:07:23 來(lái)源:網(wǎng)絡(luò) 閱讀:557 作者:匯天下豪杰 欄目:網(wǎng)絡(luò)安全

1、線程池網(wǎng)絡(luò)服務(wù)

  :針對(duì)多線程網(wǎng)絡(luò)服務(wù)模式的一些不足之處而提出的改進(jìn)模式。

  池是一個(gè)很重要的概念,其基本理念是:先創(chuàng)建一批資源,當(dāng)有用戶到來(lái)時(shí),直接分配以創(chuàng)建好的資源,它的主要目的是減少系統(tǒng)在頻繁創(chuàng)建資源時(shí)的開(kāi)銷。

  實(shí)現(xiàn)原理:主服務(wù)線程創(chuàng)建既定數(shù)量的服務(wù)線程,當(dāng)有客戶端到來(lái)時(shí),則從線程池中找出空閑的服務(wù)線程,為其服務(wù),服務(wù)完畢后,線程不進(jìn)行釋放,重新放回線程池;若當(dāng)前線程池已滿,則將當(dāng)前的客戶端加入等待隊(duì)列。

模型如下:

線程池網(wǎng)絡(luò)服務(wù)

2、代碼實(shí)現(xiàn)

  同樣用處理整數(shù)運(yùn)算來(lái)模擬線程池的并發(fā)處理

(1)、utili.h

#include<unistd.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<pthread.h>

#define SERVER_PORT  8090
#define SERVER_IP    "127.0.0.1"
#define LISTEN_QUEUE  5
#define BUFFER_SIZE   255
#define CMD_SIZE      20    

#define THREAD_POOL_NUM  5

typedef enum{ADD,SUB,MUL,DIV,MOD, QUIT}OPER_TYPE;
typedef enum{IDEL, BUSY}THREAD_TAG;

typedef struct OperStruct{
    int op1;
    int op2;
    OPER_TYPE oper;
}OperStruct;

(2)、ser.c

#include"../utili.h"

typedef struct PoolStruct{
    int sockConn;
    THREAD_TAG flag; 
}PoolStruct;

typedef PoolStruct threadpool[THREAD_POOL_NUM];
threadpool pool;
pthread_t  tid[THREAD_POOL_NUM];

void* Thread_Handler(void *arg);

void* Thread_Handler(void *arg){
    int index = *(int *)arg;

    printf("[%d] thread start up.\n", index);

    OperStruct op; 
    int result;
    while(1){
        if(pool[index].flag == BUSY){
            printf("[%d] thread start wroking.\n", index);
            int res = recv(pool[index].sockConn, &op, sizeof(op), 0); 
            if(res == -1){
                printf("recv data fail.\n");
                continue;
            }
            if(op.oper == ADD){
                result = op.op1 + op.op2;
            }else if(op.oper == SUB){
                result = op.op1 - op.op2;
            }else if(op.oper == MUL){
                result = op.op1 * op.op2;
            }else if(op.oper == DIV){
                result = op.op1 / op.op2;
            }else if(op.oper == QUIT){
                break;
            }
            res = send(pool[index].sockConn, &result, sizeof(result), 0);
            if(res == -1){
                printf("send data fail.\n");
                continue;
            }
        }else{
            printf("[%d] thread sleep.\n",index);
            sleep(1);
        }
    }
    close(pool[index].sockConn);
    pthread_exit(0);
}    
int main(void){
    int sockSer = socket(AF_INET, SOCK_STREAM, 0);
    if(sockSer == -1){
        perror("socket");
        return -1;
    }
    struct sockaddr_in addrSer, addrCli;
    addrSer.sin_family = AF_INET;
    addrSer.sin_port = htons(SERVER_PORT);
    addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

    socklen_t len = sizeof(struct sockaddr);
    int res = bind(sockSer, (struct sockaddr*)&addrSer, len);
    if(res == -1){
        perror("bind");
        close(sockSer);
        return -1;
    }

    listen(sockSer, LISTEN_QUEUE);

    int i;
    for(i=0; i<THREAD_POOL_NUM; ++i){
        pthread_create(&tid[i], NULL, Thread_Handler, &i);
        sleep(1);
    }
    for(i=0; i<THREAD_POOL_NUM; ++i){    
        pool[i].sockConn = 0;
        pool[i].flag = IDEL;
    }

    int sockConn;
    while(1){
        printf("Server Wait Client Connect.......\n");
        sockConn = accept(sockSer, (struct sockaddr*)&addrCli, &len);
        if(sockConn == -1){
            printf("Server Accept Client Connect Fail.\n");
            continue;
        }else{
            printf("Server Accept Client Connect Success.\n");
            printf("Client IP:>%s\n", inet_ntoa(addrCli.sin_addr));
            printf("Client Port:>%d\n",ntohs(addrCli.sin_port));
        }
        for(i=0; i<THREAD_POOL_NUM; ++i){
            if(pool[i].flag == IDEL){
                pool[i].flag = BUSY;
                pool[i].sockConn = sockConn;
                break;
            }
        }
    }
    close(sockSer);
    return 0;
}

(3)、cli.c

#include"utili.h"

void InputData(OperStruct *pt);

void InputData(OperStruct *pt){
    printf("please input op1 and op2 : ");
    scanf("%d %d", &(pt->op1), &(pt->op2));
}

//Cli
int main(void){
    int sockCli = socket(AF_INET, SOCK_STREAM, 0); 
    if(sockCli == -1){
        perror("socket");
        return -1; 
    }   
    struct sockaddr_in addrSer;
    addrSer.sin_family = AF_INET;
    addrSer.sin_port = htons(SERVER_PORT);
    addrSer.sin_addr.s_addr = inet_addr(SERVER_IP);

    socklen_t len = sizeof(struct sockaddr);
    int res = connect(sockCli, (struct sockaddr*)&addrSer, len);
    if(res == -1){
        perror("connect");
        close(sockCli);
        return -1; 
    }else{
        printf("Client Connect Server Success.\n");
    }

    char cmd[2];
    OperStruct  op;
    int result;
    while(1){
        printf("Please input operator : ");
        scanf("%s",cmd);
        if(strcmp(cmd, "+") == 0){
            op.oper = ADD;
            InputData(&op);
        }else if(strcmp(cmd,"-") == 0){
            op.oper = SUB;
            InputData(&op);
        }else if(strcmp(cmd,"*") == 0){
            op.oper = MUL;
            InputData(&op);
        }else if(strcmp(cmd,"/") == 0){
            op.oper = DIV;
            InputData(&op);
        }else if(strcmp(cmd, "quit") == 0){
            op.oper = QUIT;
        }else{
            printf("Cmd invalid.\n");   
       }

        res = send(sockCli, &op, sizeof(op), 0);
        if(res == -1){
            printf("send data fail.\n");
            continue;
        }
        if(op.oper == QUIT)
            break;
        res = recv(sockCli, &result, sizeof(result), 0);
        if(res == -1){
            printf("recv data fail.\n");
            continue;
        }
        printf("result = %d\n", result);
    }
    close(sockCli);
    return 0;
}

運(yùn)行結(jié)果

服務(wù)器

線程池網(wǎng)絡(luò)服務(wù)
客戶端1

線程池網(wǎng)絡(luò)服務(wù)

客戶端2

線程池網(wǎng)絡(luò)服務(wù)

3、分析總結(jié)

  (1)、其優(yōu)點(diǎn):性能高效

  (2)、可能存在的問(wèn)題:新用戶如果在等待隊(duì)列里耗時(shí)過(guò)長(zhǎng),會(huì)影響用戶體驗(yàn),針對(duì)此問(wèn)題,改進(jìn)方案如下:

  a、動(dòng)態(tài)創(chuàng)建新的服務(wù)線程,服務(wù)結(jié)束后,該線程加入線程池,這種改進(jìn)的好處是,用戶體驗(yàn)得到提升,潛在問(wèn)題是,在長(zhǎng)時(shí)間,大規(guī)模的并發(fā)用戶狀態(tài)下,線程會(huì)產(chǎn)生很多,最終會(huì)因?yàn)橘Y源消耗過(guò)多,系統(tǒng)退出。

  b、增加一個(gè)線程資源回收機(jī)制,當(dāng)線程池的規(guī)模達(dá)到一定程度或滿足某種既定規(guī)則時(shí),會(huì)主動(dòng)殺死一些線程,以達(dá)到系統(tǒng)穩(wěn)定和用戶體驗(yàn)之間折中。

模型分析

線程池網(wǎng)絡(luò)服務(wù)

  當(dāng)有客戶端來(lái),有2種做法,i>、創(chuàng)建線程為其服務(wù);ii>、加入等待隊(duì)列;這2種都不太合適,采用折中法,有一個(gè)上限值,即就是規(guī)定一個(gè)創(chuàng)建線程的最大數(shù),當(dāng)來(lái)一個(gè)用戶,還沒(méi)達(dá)到線程最大數(shù)時(shí),為其創(chuàng)建線程,若達(dá)到了,則加入等待隊(duì)列;

  對(duì)線程資源的回收:i>、立馬回收,ii>、暫時(shí)不回收;當(dāng)空閑的線程數(shù)達(dá)到某一下限值時(shí),此時(shí)再將線程回收;



向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI