udp并发服务器程序----再次修改

本文介绍了一个基于C++的多线程网络服务器的设计与实现细节。该服务器使用了线程池模型来处理客户端请求,并通过数据库连接进行数据交互。文章深入探讨了线程间同步机制、数据缓冲区管理和数据库操作等内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  1. #include <pthread.h>
  2. #include <iostream>
  3. #include <errno.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <semaphore.h>
  7. #include <netinet/in.h>
  8. #include <arpa/inet.h>
  9. #include <iterator>
  10. #include "connection.hpp"
  11. #include "table.hpp"
  12. const int NET_BUFFER_NUMBER=1024;
  13. const int THREAD_BUFFER_NUMBER=10;
  14. const int WORK_THREAD_NUMBER=100;
  15. const int THREAD_STACK_SIZE=PTHREAD_STACK_MIN*3;
  16. const int WAIT_TIME=3;
  17. //this struct for thread deal socket need data
  18. struct data_buffer
  19. {
  20.   char data_array[NET_BUFFER_NUMBER];
  21.   int data_len;//data_array actual length
  22.   struct sockaddr_in src_socket;
  23.     
  24.  
  25.   const data_buffer& operator=(const data_buffer& rhs)
  26.   {
  27.     data_len = rhs.data_len;
  28.     for (int i=0; i<data_len; i++)
  29.       {
  30.     data_array[i] = rhs.data_array[i];
  31.       }
  32.     src_socket = rhs.src_socket;
  33.     return rhs;
  34.   }
  35. };
  36. //main thread and dispatch thread
  37. struct data_buffer globe_buffer[THREAD_BUFFER_NUMBER];
  38. int globe_actual_len;//globe_buffer actual len
  39. pthread_mutex_t main_mutex;
  40. pthread_cond_t main_cond;
  41. bool can_read;
  42. //use threads pool manage
  43. //pthread_mutex_t mutex[WORK_THREAD_NUMBER];
  44. pthread_mutex_t mutex;
  45. pthread_cond_t cond;
  46. bool is_start[WORK_THREAD_NUMBER];
  47. struct thread_arg
  48. {
  49.   const struct data_buffer* ptr_data;
  50.   const int* ptr_work_len;
  51.   int self_index;//is_start array index,also mutex array
  52. };
  53. void* thread_function(void* args)
  54. {
  55.   //because of after args will changes value
  56.   struct thread_arg* ptr_arg = (struct thread_arg*)args;
  57.   int index = ptr_arg->self_index;
  58.   const struct data_buffer* ptr_src_data = ptr_arg->ptr_data;
  59.   const int* ptr_src_work_len = ptr_arg->ptr_work_len;
  60.   sqlpp::Connection conn("mysql""127.0.0.1""root""yi_jun_jun");
  61.   if (!conn.is_open())
  62.     {
  63.       perror("database connection failure");
  64.       pthread_exit(NULL);
  65.     }
  66.   sqlpp::Table table("select * from user", conn);
  67.   int my_socket = socket(AF_INET, SOCK_DGRAM, 0);
  68.   if (my_socket == -1)
  69.     {
  70.       perror("create my socket failure in thread function");
  71.       pthread_exit(NULL);
  72.     }
  73.   struct data_buffer deal_data[THREAD_BUFFER_NUMBER];
  74.   int work_count=0;
  75.   while (true)
  76.     {      
  77.       pthread_mutex_lock(&mutex);
  78.       while (!is_start[index])
  79.     {
  80.       pthread_cond_wait(&cond, &mutex);
  81.     }
  82.       work_count = *ptr_src_work_len;
  83.       for (int j=0; j<work_count; j++)
  84.     {
  85.       deal_data[j] = ptr_src_data[j];//copy self will deal data
  86.     }
  87.       pthread_mutex_unlock(&mutex);
  88.       
  89.       //copy the same data to client
  90.       for (int i=0; i<work_count; i++)
  91.     {
  92.       table.download();
  93.       sqlpp::Table::rows rows = table.get_rows<sqlpp::Table::row>();
  94.       int k = random()%rows.size();
  95.       std::copy(rows[k]["User"].begin(),rows[k]["User"].end(), deal_data[i].data_array);
  96.       deal_data[i].data_len = rows[k]["User"].size();    
  97.       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));      
  98.     }      
  99.       work_count = 0;
  100.       is_start[index] = false;//notice self is idle
  101.     }//end of while
  102.   close(my_socket);
  103.   return NULL;
  104. }
  105. bool create_threads(int create_count, struct data_buffer data_args[], int* ptr_len)
  106. {  
  107.   pthread_attr_t attr;
  108.   std::size_t stack_size;
  109.   struct thread_arg args;
  110.   args.ptr_data = data_args;
  111.   args.ptr_work_len = ptr_len;
  112.   pthread_attr_init(&attr);
  113.   pthread_attr_setstacksize(&attr, THREAD_STACK_SIZE);
  114.   for (int i=0; i<WORK_THREAD_NUMBER; i++)
  115.     {
  116.       pthread_t ptd;
  117.       args.self_index = i;
  118.       if (pthread_create(&ptd, &attr, &thread_function, (void*)&args) != 0)
  119.     {
  120.       perror("create failure");
  121.       return false;
  122.     }
  123.     }
  124.   return true;
  125. }
  126. void* dispatch(void* args)
  127. {
  128.   struct data_buffer temp[THREAD_BUFFER_NUMBER];
  129.   int work_len = 0;
  130.   if (pthread_mutex_init(&mutex, NULL) != 0)
  131.     {
  132.       perror("init lock failure in dispatch function");
  133.       pthread_exit(NULL);
  134.     }
  135.   if (pthread_cond_init(&cond, NULL) != 0)
  136.     {
  137.       perror("inin cond failure");
  138.       pthread_exit(NULL);
  139.     }
  140.   for (int i=0; i<WORK_THREAD_NUMBER; i++)
  141.     {      
  142.       is_start[i] = false;//block all work thread
  143.     }
  144.   if (!create_threads(WORK_THREAD_NUMBER, temp, &work_len))
  145.     {
  146.       perror("create threads failure");
  147.       pthread_exit(NULL);
  148.     }
  149.   while (true)
  150.     {
  151.       pthread_mutex_lock(&main_mutex);
  152.       while (!can_read)
  153.     {
  154.       pthread_cond_wait(&main_cond, &main_mutex);
  155.     }
  156.       for (int i=0; i<globe_actual_len; i++)
  157.     {
  158.       temp[i] = globe_buffer[i];
  159.     }
  160.       work_len = globe_actual_len;
  161.       //dispatch work start, if not idle thread, it will be block.
  162.       while (true)
  163.           {
  164.       int j;
  165.       for (j=0; j<WORK_THREAD_NUMBER; j++)
  166.         {
  167.           //find one idle thread, no need lock
  168.           if (!is_start[j])
  169.         {
  170.           //signal this thread start work
  171.           pthread_mutex_lock(&mutex);
  172.           is_start[j] = true;
  173.           pthread_cond_broadcast(&cond);
  174.           pthread_mutex_unlock(&mutex);
  175.           //std::cout<<"find an idle thread:"<<j<<std::endl;
  176.           break;//only break for
  177.         }
  178.         }
  179.       if (j<WORK_THREAD_NUMBER)//find one idle thread and start it
  180.         {
  181.           //std::cout<<"find an idle thread:"<<j<<std::endl;
  182.           break;//break dispatch while
  183.         }
  184.     }//end of find idle      
  185.      can_read = false;
  186.      pthread_mutex_unlock(&main_mutex);     
  187.     }//end of dispatch
  188.   pthread_mutex_destroy(&mutex);
  189.   pthread_cond_destroy(&cond);
  190. }
  191. int main(int argc, char* argv[])
  192. {
  193.   srand((unsigned long)time(NULL));
  194.   int listen_socket = socket(PF_INET, SOCK_DGRAM, 0);
  195.   if (listen_socket == -1)
  196.     {
  197.       perror("create listen socket failure");
  198.       return -1;
  199.     }
  200.   //sizeof(sockaddr_in) = sizeof(sockaddr)
  201.   //sockaddr purose = sockaddr_in purose
  202.   struct sockaddr_in addr;
  203.   bzero(&addr, sizeof(sockaddr_in));
  204.   addr.sin_family = PF_INET;
  205.   addr.sin_port = htons(1120);
  206.   addr.sin_addr.s_addr = inet_addr("127.0.0.1");
  207.   if (bind(listen_socket, (sockaddr*)&addr, sizeof(sockaddr_in)) == -1)
  208.     {
  209.       perror("bind listen_socket failure");
  210.       close(listen_socket);
  211.       return -1;
  212.     }
  213.   timeval timeout = {WAIT_TIME,0};
  214.   if (setsockopt(listen_socket, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval)) == -1)
  215.     {
  216.       perror("set time out failure");
  217.       close(listen_socket);
  218.       return -1;
  219.     }
  220.  
  221.   if (pthread_mutex_init(&main_mutex, NULL) != 0)
  222.     {
  223.       perror("main_mutex init failure");
  224.       close(listen_socket);
  225.       return -1;
  226.     }
  227.   if (pthread_cond_init(&main_cond, NULL) != 0)
  228.     {
  229.       perror("main_cond init failure");
  230.       close(listen_socket);
  231.       return -1;
  232.     }
  233.   //create distpach thread
  234.   can_read = false;
  235.   globe_actual_len = 0;
  236.   pthread_t pt;
  237.   if (pthread_create(&pt, NULL, &dispatch, NULL) != 0)
  238.     {
  239.       perror("create dispatch thread failure");
  240.       close(listen_socket);
  241.       return -1;
  242.     }
  243.   //main receive loop
  244.   char buffer[NET_BUFFER_NUMBER];
  245.   bzero(buffer, sizeof(buffer));
  246.   struct sockaddr_in client;
  247.   int actual_len=0;
  248.   socklen_t sock_len = sizeof(sockaddr_in);
  249.   struct data_buffer temp[THREAD_BUFFER_NUMBER];
  250.   int index=0;  
  251.   while (true)
  252.     {
  253.       if ((actual_len=recvfrom(listen_socket, buffer, NET_BUFFER_NUMBER, 0, (sockaddr*)&client, &sock_len)) <= 0)
  254.     {      
  255.       //maybe it is timeout,check exists old socket not dispatch
  256.       if ((index>0) && (index<=THREAD_BUFFER_NUMBER))
  257.         {          
  258.           pthread_mutex_lock(&main_mutex);
  259.           globe_actual_len = index;          
  260.           for (int i=0; i<globe_actual_len; i++)
  261.         {
  262.           globe_buffer[i] = temp[i];
  263.         }          
  264.           index = 0;
  265.           can_read = true;          
  266.           pthread_cond_broadcast(&main_cond);          
  267.           pthread_mutex_unlock(&main_mutex);
  268.         }
  269.       continue;
  270.     }
  271.       else
  272.     {      
  273.       if ( index >= THREAD_BUFFER_NUMBER)
  274.         {          
  275.           pthread_mutex_lock(&main_mutex);
  276.           globe_actual_len = THREAD_BUFFER_NUMBER;          
  277.           for (int i=0; i<globe_actual_len; i++)
  278.         {
  279.           globe_buffer[i] = temp[i];
  280.         }          
  281.           index = 0;
  282.           can_read = true;          
  283.           pthread_cond_broadcast(&main_cond);          
  284.           pthread_mutex_unlock(&main_mutex);
  285.         }
  286.       temp[index].data_len = actual_len;
  287.       for (int k=0; k<actual_len; k++)
  288.         {
  289.           temp[index].data_array[k] = buffer[k];
  290.         }
  291.       temp[index++].src_socket = client;
  292.     }
  293.     }
  294.   pthread_mutex_destroy(&main_mutex);
  295.   pthread_cond_destroy(&main_cond);
  296.   return 0;
  297. }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值