C语言实现TCP服务器----模型(三)

头文件:

#ifndef SERVER_HEAD
#define SERVER_HEAD
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/epoll.h>
#include <assert.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string.h>
#include <netdb.h>


#define PORT 8888
#define PATH "192.168.106.28"
#define MAXSIZE 20


typedef struct work
{
    void*(*process)(void* arg);
    void* arg;
    struct work * next;
}WORK;


typedef struct
{
    pthread_mutex_t queue_lock;
    pthread_cond_t queue_ready;
    WORK * queue_head;
    int shutdown;
    pthread_t * pthreadid;
    int max_thread_num;
    int cur_queue_size;
}POOL;


static char name[20][20];
static int sockli[20]={0};
static POOL *pool=NULL;
int sock_create();
void int_bind_listen(int sockfd);
void accept_fun(int sockfd,struct sockaddr_in addr);
void epoll_fun(int sockfd,struct sockaddr_in addr);
void* pthread_routine(void * arg);
void pool_init(int max_num);
int add_work(void*(process)(void *arg),void* arg );
int pool_destroy();
void *task_fun(void *arg);
#endif // SERVER_HEAD


function.c 文件

#include "server3_head.h"
//using namespace std;


//创建套接字
int sock_create()
{
    int sockfd=socket(AF_INET,SOCK_STREAM,0);
    if(sockfd<0)
        {
        perror("socket failed!\n");
        exit(1);
    }
    printf("socket success!\n");
    return sockfd;
}
//初始化、绑定、监听
void int_bind_listen(int sockfd)
{
    struct sockaddr_in addr;
    addr.sin_family=AF_INET;
    addr.sin_port=htons(PORT);
    addr.sin_addr.s_addr=inet_addr(PATH);
    bzero(addr.sin_zero,8);
    if((bind(sockfd,(struct sockaddr *)&addr,sizeof(struct sockaddr)))!=0)
        {
        perror("bind failed!\n");
        exit(1);
    }
    printf("bind success!\n");
    if((listen(sockfd,MAXSIZE))!=0)
        {
        perror("listen failed!\n");
        exit(1);
    }
    printf("listen success!\n");
}
//epoll监听函数
void epoll_fun(int sockfd,struct sockaddr_in addr)
{
    int i,j=0;
    int epfd;
    int newfd;
    int evnum;
    int recbytes;
    struct epoll_event ep;
    struct epoll_event events[MAXSIZE];
    socklen_t addr_len=sizeof(struct sockaddr);
    epfd=epoll_create(MAXSIZE);
    ep.data.fd =sockfd;
    ep.events = EPOLLIN | EPOLLET;
    epoll_ctl(epfd,EPOLL_CTL_ADD,sockfd,&ep);
    while(1)
 {
        evnum=epoll_wait(epfd,events,MAXSIZE,-1);
        if(evnum==0)
            {
            printf("time out!\n");
            }
         else if(evnum==-1)
          {
            printf("stop at this time forever!\n") ;
            }
            else{
                printf("epoll success!evnum=%d\n",evnum);
            }
            for(int i=0;i<evnum;i++)
                {
                if(events[i].data.fd==sockfd)
                    {
                     newfd=accept(sockfd,(struct sockaddr *)&addr,&addr_len);
                    if(newfd==-1)
                        {
                        perror("accept failed!\n");
                    }
                    else
                        {
                        sockli[j]=newfd;
                        printf("%d\n",sockli[j]);
                        j++;
                        ep.data.fd =newfd;
                        ep.events = EPOLLIN | EPOLLET;
                        epoll_ctl(epfd,EPOLL_CTL_ADD,newfd,&ep);
                    }
                }
                else if(events[i].events&EPOLLIN)
                {
                        ep.data.fd =events[i].data.fd;
                        ep.events  = EPOLLOUT | EPOLLET;
                        epoll_ctl(epfd,EPOLL_CTL_MOD,ep.data.fd,&ep);
                        add_work(task_fun,(void *)(events[i].data.fd));
                }
            }
         }
    }
//服务器接收客户端链接函数
void accept_fun(int sockfd,struct sockaddr_in addr)
{
    int recvbytes=0;
    int i=0;
    int ret=-1;
    socklen_t addr_len=sizeof(struct sockaddr);
    while(1)
        {
             sockli[i]=accept(sockfd,(struct sockaddr*)&addr,&addr_len);
             if(sockli[i]<0)
             {
             perror("accept failed!\n");
                }
            else{
             printf("accept success!\n");
                }
             recvbytes=recv(sockli[i],name[i],20,0);
             if(recvbytes==-1)
                 {
                 perror("recv failed in accept_fun!\n");
             }else
                 {
                 printf("recv %d bytes to name\n");
                 name[i][recvbytes]='\0';
                 printf("name=%s\n",name[i]);
             }
             printf("i=%d\n",i);
             printf("%d\n",sockli[i]);
             ret=add_work((task_fun),(void*) i);
             if(ret!=0)
                 {
                 perror("add failed!\n");
             }
             i++;
         }
}
/*
//回调函数
void* task_fun(void * arg)
{
    int a=(int)arg;
    printf("%d\n",sockli[(a)]);
    sleep(5);
    int recvbytes=0;
    int i,j,k;
    int sent=0;
    char news[100];
    while(1)
        {
            recvbytes=recv(sockli[a],news,sizeof(news),0);
            if ( recvbytes == -1)
                {
                    perror("recv failed in task_fun!\n");
                 }
             else if(recvbytes==0)
            {
                    printf("client is closed!\n");
                    break;
            }
             else{
                printf("recv %d bytes from client\n",recvbytes);
                    news[recvbytes]='\0';
                    printf("news=%s\n",news);
              }
              for(j=0;sockli[j]!=0;j++)
              {
                    if(sockli[j]==sockli[a])
                        {
                        continue;
                    }
                    sent=send(sockli[j],name[a],strlen(name[a]),0);
                    sent=send(sockli[j],news,strlen(news),0);
                    if(sent==-1)
                        {
                        perror("send failed!\n");
                    }
                    else{
                        printf("send %d bytes to client\n",sent);
                    }
              }
         }
    pthread_exit(NULL);
}
*/
//回调函数 epoll
void* task_fun(void * arg)
{
    printf("aaaaaaaaaaa\n");
    int a=(int)arg;
    int recvbytes=0;
    int i,j,k;
    int sent=0;
    char news[100];
    while(1)
        {
            recvbytes=recv(a,news,sizeof(news),0);
            if ( recvbytes == -1)
                {
                    perror("recv failed in task_fun!\n");
                 }
             else if(recvbytes==0)
            {
                    printf("client is closed!\n");
                    break;
            }
             else{
                printf("recv %d bytes from client\n",recvbytes);
                    news[recvbytes]='\0';
                    printf("news=%s\n",news);
              }
              for(j=0;sockli[j]!=0;j++)
              {
                    if(sockli[j]==a)
                        {
                        continue;
                    }
            //        sent=send(sockli[j],name[a],strlen(name[a]),0);
                    sent=send(sockli[j],news,strlen(news),0);
                    if(sent==-1)
                        {
                        perror("send failed!\n");
                    }
                    else{
                        printf("send %d bytes to client\n",sent);
                    }
              }
         }
    pthread_exit(NULL);
}
//线程处理函数
void* pthread_routine(void *args)
{
    printf("this is in pthread_routine\n");
    while(1)
    {
        pthread_mutex_lock(&(pool->queue_lock));
        while(pool->cur_queue_size==0&& !pool->shutdown)
        {
            pthread_cond_wait(&(pool->queue_ready),&(pool->queue_lock));
        }
        if(pool->shutdown)
        {
            pthread_mutex_unlock(&(pool->queue_lock));
            pthread_exit(NULL);
        }
        printf("ready to start\n");
        assert(pool->cur_queue_size !=0);
        assert(pool->queue_head !=NULL);
        pool->cur_queue_size--;
        WORK* worker=pool->queue_head;
        pool->queue_head=worker->next;
        pthread_mutex_unlock(&(pool->queue_lock));
        (*(worker->process))(worker->arg);
        free(worker);
        worker=NULL;
    }
    pthread_exit(NULL);
}
// 线程池初始化
 void pool_init(int max_num)
{
    int i;
    pool=(POOL*)malloc(sizeof(POOL));
    pthread_mutex_init(&(pool->queue_lock),NULL);
    pthread_cond_init(&(pool->queue_ready),NULL);
    pool->queue_head=NULL;
    pool->max_thread_num=max_num;
    pool->cur_queue_size=0;
    pool->pthreadid=(pthread_t *)malloc((pool->max_thread_num) * sizeof(pthread_t));
    for(i=0;i<max_num;i++)
    {
        pthread_create(&(pool->pthreadid[i]),NULL,pthread_routine,NULL);
        printf("%d\n",pool->pthreadid[i]);
    }
}
 //添加任务队列
 int add_work(void*(process)(void* arg),void *arg)
 {
     WORK* newwork=(WORK*)malloc(sizeof(WORK));
     newwork->process=process;
     newwork->arg=arg;
     newwork->next=NULL;
     pthread_mutex_lock(&(pool->queue_lock));
     WORK* member=pool->queue_head;
     if(member !=NULL)
     {
         while(member->next !=NULL)
         {
             member=member->next;
         }
     }
     else{
         pool->queue_head=newwork;
     }
     assert(pool->queue_head !=NULL);
     pool->cur_queue_size ++;
     pthread_mutex_unlock(&(pool->queue_lock));
     pthread_cond_signal(&(pool->queue_ready));
     return 0;
 }
 //清空线程池
 int pool_destroy()
 {
     if(pool->shutdown)
     {
             return -1;
      }
      pool->shutdown=-1;
      pthread_cond_broadcast(&(pool->queue_ready));
      int i;
      for(i=0;i<pool->max_thread_num;i++)
      {
          pthread_join((pool->pthreadid[i]),NULL);
      }
      free(pool->pthreadid);
      WORK* head=NULL;
      while(pool->queue_head !=NULL)
      {
          head=pool->queue_head;
          pool->queue_head=pool->queue_head->next;
          free(head);
      }
      pthread_mutex_destroy(&(pool->queue_lock));
      pthread_cond_destroy(&(pool->queue_ready));
      free(pool);
      pool=NULL;


 }


main.c 文件

#include "server3_head.h"



int main()
{
    int sockfd;
   struct sockaddr_in client_addr;
   pool_init(10);
   sockfd=sock_create();
   int_bind_listen(sockfd);
   epoll_fun(sockfd,client_addr);
   pool_destroy();
   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值