udp并发服务器程序----初步

#include <pthread.h>
#include <iostream>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <semaphore.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <iterator>

const int NET_BUFFER_NUMBER=1024;
const int THREAD_BUFFER_NUMBER=10;
const int WORK_THREAD_NUMBER=20;

//this struct for thread deal socket need data
struct data_buffer
{
  char data_array[NET_BUFFER_NUMBER];
  int data_len;
  struct sockaddr_in src_socket;
    
 
  const data_buffer& operator=(const data_buffer& rhs)
  {
    data_len = rhs.data_len;

    for (int i=0; i<data_len; i++)
      {
    data_array[i] = rhs.data_array[i];
      }
    src_socket = rhs.src_socket;
    return rhs;
  }
};

//main thread and dispatch thread
struct data_buffer globe_buffer[THREAD_BUFFER_NUMBER];
pthread_mutex_t main_mutex;
pthread_cond_t main_cond;
bool can_read;

//use threads pool manage
//pthread_mutex_t mutex[WORK_THREAD_NUMBER];
pthread_mutex_t mutex;
pthread_cond_t cond;
bool is_start[WORK_THREAD_NUMBER];
struct thread_arg
{
  const struct data_buffer* ptr_data;
  int self_index;//is_start array index,also mutex array
};

void* thread_function(void* args)
{
  //because of after args will changes value
  struct thread_arg* ptr_arg = (struct thread_arg*)args;
  int index = ptr_arg->self_index;
  const struct data_buffer* ptr_src_data = ptr_arg->ptr_data;
  //std::cout<<"create thread index is:"<<index<<"/t data address is:"<<ptr_src_data<<std::endl;
  int my_socket = socket(AF_INET, SOCK_DGRAM, 0);
  if (my_socket == -1)
    {
      perror("create my socket failure in thread function");
      pthread_exit(NULL);
    }
  struct data_buffer deal_data[THREAD_BUFFER_NUMBER];
  while (true)
    {      
      pthread_mutex_lock(&mutex);
      while (!is_start[index])
    {
      pthread_cond_wait(&cond, &mutex);
    }
      for (int j=0; j<THREAD_BUFFER_NUMBER; j++)
    {
      deal_data[j] = ptr_src_data[j];//copy self will deal data
    }
      pthread_mutex_unlock(&mutex);
     
      //copy the same data to client
      for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
    {
      sleep(5);
      sendto(my_socket, deal_data[i].data_array, deal_data[i].data_len, 0, (sockaddr*)&(deal_data[i].src_socket), sizeof(deal_data[i].src_socket));      
    }
      is_start[index] = false;//notice self is idle
    }//end of while
  close(my_socket);
  return NULL;
}

bool create_threads(int create_count, struct data_buffer data_args[])
{  
  pthread_attr_t attr;
  std::size_t stack_size;
  struct thread_arg args;
  args.ptr_data = data_args;
  pthread_attr_init(&attr);
  pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN*3);
  for (int i=0; i<WORK_THREAD_NUMBER; i++)
    {
      pthread_t ptd;
      args.self_index = i;
      if (pthread_create(&ptd, &attr, &thread_function, (void*)&args) != 0)
    {
      perror("create failure");
      return false;
    }
    }
  return true;
}

void* dispatch(void* args)
{
  struct data_buffer temp[THREAD_BUFFER_NUMBER];

  if (pthread_mutex_init(&mutex, NULL) != 0)
    {
      perror("init lock failure in dispatch function");
      pthread_exit(NULL);
    }

  if (pthread_cond_init(&cond, NULL) != 0)
    {
      perror("inin cond failure");
      pthread_exit(NULL);
    }

  for (int i=0; i<WORK_THREAD_NUMBER; i++)
    {      
      is_start[i] = false;//block all work thread
    }

  if (!create_threads(WORK_THREAD_NUMBER, temp))
    {
      perror("create threads failure");
      pthread_exit(NULL);
    }

  while (true)
    {
      pthread_mutex_lock(&main_mutex);
      while (!can_read)
    {
      pthread_cond_wait(&main_cond, &main_mutex);
    }
      std::cout<<"sem wait wake up"<<std::endl;

      //forbidden main loop thread write data,or maybe read dirty data
      //pthread_mutex_lock(&main_mutex);
      //if last work thread can not complete copy data, we can not write to temp
      for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
    {
      temp[i] = globe_buffer[i];
    }

      //dispatch work start, if not idle thread, it will be block.
      while (true)
    {
      int j;
      for (j=0; j<WORK_THREAD_NUMBER; j++)
        {
          //find one idle thread, no need lock
          if (!is_start[j])
        {
          //signal this thread start work
          pthread_mutex_lock(&mutex);
          is_start[j] = true;
          pthread_cond_broadcast(&cond);
          pthread_mutex_unlock(&mutex);
          break;//only break for
        }
        }
      if (j<WORK_THREAD_NUMBER)//find one idle thread and start it
        {
          std::cout<<"find an idle thread:"<<j<<std::endl;
          break;//break dispatch while
        }
    }//end of find idle
      //std::cout<<"dispatch successful"<<std::endl
     can_read = false;
     pthread_mutex_unlock(&main_mutex);      
    }//end of dispatch
  pthread_mutex_destroy(&mutex);
  pthread_cond_destroy(&cond);
}

int main(int argc, char* argv[])
{
  int listen_socket = socket(PF_INET, SOCK_DGRAM, 0);
  if (listen_socket == -1)
    {
      perror("create listen socket failure");
      return -1;
    }

  //sizeof(sockaddr_in) = sizeof(sockaddr)
  //sockaddr purose = sockaddr_in purose
  struct sockaddr_in addr;
  bzero(&addr, sizeof(sockaddr_in));
  addr.sin_family = PF_INET;
  addr.sin_port = htons(1120);
  addr.sin_addr.s_addr = inet_addr("127.0.0.1");

  if (bind(listen_socket, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1)
    {
      perror("bind listen_socket failure");
      close(listen_socket);
      return -1;
    }
 
  if (pthread_mutex_init(&main_mutex, NULL) != 0)
    {
      perror("main_mutex init failure");
      close(listen_socket);
      return -1;
    }

  if (pthread_cond_init(&main_cond, NULL) != 0)
    {
      perror("main_cond init failure");
      close(listen_socket);
      return -1;
    }

  //create distpach thread
  can_read = false;
  pthread_t pt;
  if (pthread_create(&pt, NULL, &dispatch, NULL) != 0)
    {
      perror("create dispatch thread failure");
      close(listen_socket);
      return -1;
    }

  //main receive loop
  char buffer[NET_BUFFER_NUMBER];
  bzero(buffer, sizeof(buffer));
  struct sockaddr_in client;
  int actual_len=0;
  socklen_t sock_len = sizeof(sockaddr_in);
  struct data_buffer temp[THREAD_BUFFER_NUMBER];
  int index=0;
  while (true)
    {
      if ((actual_len=recvfrom(listen_socket, buffer, NET_BUFFER_NUMBER, 0, (sockaddr*)&client, &sock_len)) == -1)
    {      
      //allow error
      continue;
    }
      else
    {
      if (index >= THREAD_BUFFER_NUMBER)
        {
          pthread_mutex_lock(&main_mutex);          
          for (int i=0; i<THREAD_BUFFER_NUMBER; i++)
        {
          globe_buffer[i] = temp[i];
        }          
          index = 0;
          can_read = true;
          pthread_cond_broadcast(&main_cond);
          pthread_mutex_unlock(&main_mutex);
        }
      else
        {
          temp[index].data_len = actual_len;
          for (int k=0; k<actual_len; k++)
        {
          temp[index].data_array[k] = buffer[k];
        }
          temp[index++].src_socket = client;
        }
    }
    }
  pthread_mutex_destroy(&main_mutex);
  pthread_cond_destroy(&main_cond);
  return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值