TCP实现线程池竞争任务

服务端:

cpp 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<strings.h>
#include<unistd.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<pthread.h>

#define SERV_PORT 8000
#define MAXLINE 80


//打印报错信息
#define prrexit(msg){ \
     perror(msg); \
    exit(1); \
 }

typedef struct Task{
    int fd;
    struct Task  *next;
}Task;
//任务池子,队列
typedef struct Task_pool{
    Task *head;
    Task *tail;
    pthread_mutex_t lock;
    pthread_cond_t havetask;
}Task_pool;

Task_pool *task_pool_init(){
    Task_pool *tp=(Task_pool *)malloc(sizeof(Task_pool));
    tp->head=NULL;
    tp->tail=NULL;
    pthread_mutex_init(&tp->lock,NULL);
    pthread_cond_init(&tp->havetask,NULL);

    return tp;
}


void task_pool_push( Task_pool *tp,int fd){
    pthread_mutex_lock(&tp->lock);
    Task *t=(Task *)malloc(sizeof(Task));
    t->fd=fd;
    t->next=NULL;
    //两种情况
    if(!tp->tail){
       tp-> head=tp->tail=t;
    }else{
     tp->tail->next=t;
     tp-> tail=t;
    }

    pthread_cond_broadcast(&tp->havetask);

    pthread_mutex_unlock(&tp->lock);
}


Task task_pool_pop(Task_pool *tp){
    pthread_mutex_lock(&tp->lock);

    //为什么不能用if
    while(tp->head==NULL){
        pthread_cond_wait(&tp->havetask,&tp->lock);
        
    }


    Task tmp,*k;
    k=tp->head;
    tmp=*k;
    tp->head=tp->head->next;
    //队列一开始为空的情况下
    if(!tp->head){
        tp->tail=NULL;
    }
    free(k);
    pthread_mutex_unlock(&tp->lock);
    return tmp;
}

void task_pool_free(Task_pool *tp){
   pthread_mutex_lock(&tp->lock);
    Task *p=tp->head,*k;

    while(p){
        k=p;
        p=p->next;
        free(k);
    }
    tp->head=NULL;

    pthread_mutex_unlock(&tp->lock);
    pthread_mutex_destroy(&tp->lock);
    pthread_cond_destroy(&tp->havetask);
    free(tp);
    
    return ;
}





//子线程
void *up_server(void *arg){
    //获取自己的线程id,自我释放
    pthread_detach(pthread_self());

//进行安全的类型转换
      //  int connfd=(int)(intptr_t)arg;
        char buff[MAXLINE];
        int n,i;

        Task_pool *tp=arg;
        
    while(1){ 
        Task tmp=task_pool_pop(tp);
        int connfd=tmp.fd;
        printf("get task fd=%d\n",connfd);
        while(1){
            n=read(connfd,buff,MAXLINE);
            if(n<=0){
                perror("read error  or connections closed");
                break;
        }

            buff[n]='\0';//添加字符串终止符
            write(1,buff,n);

            if(strncmp(buff,"quit",4)==0){
                break;
            }

        
            for(i = 0; i < n ; i++)
            buff[i]=toupper(buff[i]);

            write(connfd,buff,n);
        }
        printf("finish task fd=%d\n",connfd);
        close(connfd);
    }
    //正常退出
    return (void *)0;
}

int main(){
    struct sockaddr_in serveraddr,claddr;
    int listenfd, connfd;
    socklen_t  claddr_len;

   // char buff[MAXLINE];
    char str[INET_ADDRSTRLEN];
    int n,i;
    //任务池创建
    Task_pool *tp=task_pool_init();
 
    //多线程   
    pthread_t  tid;
    //多少核就多少个
    //一上来就会打印id
    for(i=0;i<4;i++){
    pthread_create(&tid,NULL,up_server,(void *)(intptr_t)tp);
    printf("new thread is %#lx\n",tid);
    }


    listenfd =socket(AF_INET,SOCK_STREAM,0);
    if(listenfd<0){
        prrexit("socket");
    }

    //服务器ip地址,端口初始化
    bzero(&serveraddr,sizeof(serveraddr));
    serveraddr.sin_family=AF_INET;
    serveraddr.sin_port = htons(SERV_PORT);
    serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

    if(bind(listenfd,(struct  sockaddr *)&serveraddr,sizeof(serveraddr))<0)
    prrexit("bind");


    if(listen(listenfd,3)<0)
    prrexit("listen");

    printf("Accepting connections...\n");

    while(1){
        claddr_len= sizeof(claddr);
        connfd=accept(listenfd,(struct sockaddr *)&claddr,&claddr_len);
        if(connfd<0)
        prrexit("accept");

        printf("received from %s:%d\n",
               inet_ntop(AF_INET,&claddr.sin_addr,str,sizeof(str)),
               ntohs(claddr.sin_port));

        /*多进程
        pid_t pid= fork();
        if(pid<0){
        prrexit("fork");
    }
        //父进程 :等待 创建连接
        if(pid > 0){
        close(connfd);
        //回收进程资源
        while(waitpid(-1,NULL,WNOHANG)>0){ };

        continue;
    }

        close(listenfd);

        */

        //多线程
      //  pthread_t  tid;
      //  pthread_create(&tid,NULL,up_server,(void *)(intptr_t)connfd);
      //  printf("new thread is %#lx\n",tid);
   
    
    task_pool_push(tp,connfd);
    }
    
    task_pool_free(tp);
     return 0;
}

客户端:

cpp 复制代码
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<string.h>
#include<unistd.h>
#include<ctype.h>
#include<arpa/inet.h>
#include<stdlib.h>


#define SERV_PORT 8000
#define MAXLINE 80

int main(){
    struct  sockaddr_in servaddr;
    char buff[MAXLINE];
    int sockfd = socket(AF_INET, SOCK_STREAM,0);
    
    if(sockfd < 0){
        perror("socket");
        exit(1);
    }

    bzero(&servaddr,sizeof(servaddr));

    servaddr.sin_family=AF_INET;
    servaddr.sin_port = htons(SERV_PORT);

    inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);

    if(connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr))<0){
        perror("cnnect");
        exit(1);
    }
    
    printf("Connect to server .Type 'quit' to exit.\n");

    //死循环进行读入
    int n;
    while((n=read(0,buff,MAXLINE))>0){
    
    if(n > 0)buff[n-1] = '\0';

    //边界检查,只比较前四个字节
    if(strncmp(buff,"quit",4)==0){
        printf("Quitting ..\n");
        write(sockfd,buff,strlen(buff));
        break;
    }
    
    ssize_t bytes_written =write(sockfd,buff,strlen(buff));
     if(bytes_written!=strlen(buff)){
            perror("write error");
            break;
        }
    //读取云服务器响应
    n = read(sockfd,buff,MAXLINE);
        if(n<=0){
            if(n==0){
                printf("Server closed the connection.\n");
            }else{
                perror("read error");
            }
            break;
        }
        
        buff[n] = '\0';//确保响应字符串正确终止

        printf("Server  response: %s\n",buff);
        printf("Enter next message : ");
        fflush(stdout);//强制刷新输出缓冲区
        
    }  

    if(n<0){
        perror("read from stdin error");
    }
    close(sockfd);
    printf("Client exited.\n");
    return 0;
}
相关推荐
sunfove13 小时前
光网络的立交桥:光开关 (Optical Switch) 原理与主流技术解析
网络
Kevin Wang72715 小时前
欧拉系统服务部署注意事项
网络·windows
min18112345615 小时前
深度伪造内容的检测与溯源技术
大数据·网络·人工智能
汤愈韬15 小时前
NAT策略
网络协议·网络安全·security·huawei
汤愈韬16 小时前
Full Cone Nat
网络·网络协议·网络安全·security·huawei
zbtlink16 小时前
现在还需要带电池的路由器吗?是用来干嘛的?
网络·智能路由器
桌面运维家16 小时前
vDisk配置漂移怎么办?VOI/IDV架构故障快速修复
网络·架构
dalerkd16 小时前
忙里偷闲叙-谈谈最近两年
网络·安全·web安全
汤愈韬17 小时前
NAT ALG (应用层网关)
网络·网络协议·网络安全·security·huawei
运维栈记18 小时前
虚拟化网络的根基-网络命名空间
网络·docker·容器