zoukankan      html  css  js  c++  java
  • Linux网络编程服务器模型选择之并发服务器(下)

           前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率较低,同一时刻只能为一个客户端提供服务,而且对于TCP模型来说,还存在单客户端长久独占与服务器的连接,无法再响应其他连接,对于前面介绍的并发服务器模型是比较简单的,比如由于预先分配了固定进程数目,就导致无法动态调整等问题。在前面我们也提到了对accept函数的处理是区分不同服务器模型的一个重要依据,当然UDP服务器并不需要accept函数,因此本次主要介绍TCP的高级并发模型。按照对accept的不同处理,接下来主要介绍以下几种并发模型:

    1. 单客户端单进程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个进程用于响应;
    2. 单客户端单线程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个线程用于响应;
    3. 单客户端单线程,各自accept :预先分配多个线程,在每一个线程里都独自等待客户端的连接并响应(注意accept需要互斥访问);

    并发模型伪代码

    /* 单客户端单进程,统一accept */ 
    /* 服务器主进程 */
      socket();
      bind();
      listen();
      while(1)
      {
        accept();
        fork();//子进程
      }
      close(); //关闭服务器端套接字
      
    /* 服务器子进程1 */  
     recv();
     process();
     send();
     close();//关闭客户端套接字
     
    /* 服务器子进程2(同上) */
    ..................
    /* 单客户端单线程,统一accept */ 
    /* 服务器主进程 */
      socket();
      bind();
      listen();
      while(1)
      {
        accept();
        pthread_create(); //创建响应线程
     }
     close();//关闭服务器端套接字
    
    /* 服务器线程1 */
    recv();
    process();
    send();
    close();//关闭客户端套接字
    /* 服务器线程2(同上)  */
    ..................
    /* 单客户端单线程,各自accept */ 
    /* 服务器主进程 */
     socket();
     bind();
     listen();
     pthread_create();//创建多个线程分别等待客户端连接
     pthread_join();//等待线程结束
     close();//关闭服务器端套接字
     
    /* 服务器线程1 */
    mutex_lock()//互斥锁
    accept();
    mutex_unlock();
    
    recv();
    process();
    send();
    close();//客户端套接字
    /* 服务器线程2(同上)  */
    ..................

    一个高级并发服务器模型的例子

    单客户端单进程,统一accept  server端程序
     1 /* 单客户端单进程,统一accept  --server端程序*/ 
     2 #include <sys/types.h>
     3 #include <sys/socket.h>
     4 #include <netinet/in.h>
     5 #include <time.h>
     6 #include <string.h>
     7 #include <stdio.h>
     8 #define BUFFLEN 1024
     9 #define SERVER_PORT 12348
    10 #define BACKLOG 5
    11 
    12 static void handle_request(int s_c)
    13 {
    14     time_t now;        
    15     char buff[BUFFLEN];
    16     int n = 0;
    17     memset(buff, 0, BUFFLEN);
    18     n = recv(s_c, buff, BUFFLEN,0);
    19     if(n > 0 && !strncmp(buff, "TIME", 4))
    20     {
    21         memset(buff, 0, BUFFLEN);
    22         now = time(NULL);
    23         sprintf(buff, "%24s
    ",ctime(&now));
    24         send(s_c, buff, strlen(buff),0);
    25     }        
    26     
    27     close(s_c);    /*关闭客户端*/
    28 }
    29 
    30 static void handle_connect(int s_s)
    31 {
    32     
    33     int s_c;    /*客户端套接字文件描述符*/
    34     struct sockaddr_in from;    /*客户端地址*/
    35     int len = sizeof(from);
    36     
    37     /*主处理过程*/
    38     while(1)
    39     {        
    40         s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端连接*/
    41         if(s_c > 0)/*客户端成功连接,创建进程进行数据处理*/
    42         {
    43             if(fork() > 0)  /*父进程*/
    44             {
    45                 close(s_c); /*关闭父进程的客户端连接套接字*/
    46             }
    47             else
    48             {
    49                 handle_request(s_c);/*处理连接请求*/
    50             }
    51         }
    52     }        
    53 }
    54 
    55 int main(int argc, char *argv[])
    56 {
    57     int s_s;    /*服务器套接字文件描述符*/
    58     struct sockaddr_in local;    /*本地地址*/    
    59     
    60     /*建立TCP套接字*/
    61     s_s = socket(AF_INET, SOCK_STREAM, 0);
    62     
    63     /*初始化地址*/
    64     memset(&local, 0, sizeof(local));
    65     local.sin_family = AF_INET;/*AF_INET协议族*/
    66     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
    67     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
    68     
    69     /*将套接字文件描述符绑定到本地地址和端口*/
    70     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
    71     err = listen(s_s, BACKLOG);/*侦听*/
    72     
    73     /*处理客户端连接*/
    74     handle_connect(s_s);
    75     
    76     close(s_s);
    77     
    78     return 0;        
    79 }
    单客户端单进程,统一accept  server端程序
     1 单客户端单进程,统一accept  server端程序
     2 #include <sys/types.h>
     3 #include <sys/socket.h>
     4 #include <netinet/in.h>
     5 #include <time.h>
     6 #include <string.h>
    #include <pthread> 7 #include <stdio.h> 8 #define BUFFLEN 1024 9 #define SERVER_PORT 12348 10 #define BACKLOG 5 11 12 static void *handle_request(void *argv) 13 { 14 int s_c = *((int*)argv); 15 time_t now; 16 char buff[BUFFLEN]; 17 int n = 0; 18 memset(buff, 0, BUFFLEN); 19 n = recv(s_c, buff, BUFFLEN,0); 20 if(n > 0 && !strncmp(buff, "TIME", 4)) 21 { 22 memset(buff, 0, BUFFLEN); 23 now = time(NULL); 24 sprintf(buff, "%24s ",ctime(&now)); 25 send(s_c, buff, strlen(buff),0); 26 } 27 28 close(s_c); /*关闭客户端*/ 29 } 30 31 static void handle_connect(int s_s) 32 { 33 int s_c; /*客户端套接字文件描述符*/ 34 struct sockaddr_in from; /*客户端地址*/ 35 int len = sizeof(from); 36 pthread_t thread_do; 37 38 /*主处理过程*/ 39 while(1) 40 { 41 s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端连接*/ 42 if(s_c > 0)/*客户端成功连接,创建线程进行数据处理*/ 43 { 44 int err = pthread_create(&thread_do,NULL,handle_request,(void*)&s_c; 45 } 46 } 47 } 48 49 int main(int argc, char *argv[]) 50 { 51 int s_s; /*服务器套接字文件描述符*/ 52 struct sockaddr_in local; /*本地地址*/ 53 54 s_s = socket(AF_INET, SOCK_STREAM, 0);/*建立TCP套接字*/ 55 56 /*初始化地址*/ 57 memset(&local, 0, sizeof(local)); 58 local.sin_family = AF_INET;/*AF_INET协议族*/ 59 local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/ 60 local.sin_port = htons(SERVER_PORT);/*服务器端口*/ 61 62 /*将套接字文件描述符绑定到本地地址和端口*/ 63 int err = bind(s_s, (struct sockaddr*)&local, sizeof(local)); 64 err = listen(s_s, BACKLOG);/*侦听*/ 65 66 /*处理客户端连接*/ 67 handle_connect(s_s); 68 69 close(s_s); 70 71 return 0; 72 }

    单客户端单线程,各自accept --server端程序

    /** 单客户端单线程,各自accept --server端程序 */
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <time.h>
    #include <string.h>
    #include <stdio.h>
    #include <pthread>
    #define BUFFLEN 1024
    #define SERVER_PORT 12348
    #define BACKLOG 5
    #define CLIENT_NUM 3
    
    pthread_mutex_t g_lock = PTHREAD_MUTEX_INTIALIZER;
    
    
    static void *handle_request(void *argv)
    {
        int s_s = *((int*)argv); //服务器端套接字
        struct sockaddr_in from;    /*客户端地址*/
        int len = sizeof(from);
        int s_c = -1; //客户端套接字
        for( ; ; )
        {
            time_t now;        
            char buff[BUFFLEN];
            int n = 0;
            memset(buff, 0, BUFFLEN);
            
            pthread_mutex_lock(&g_lock);
            s_c = accept(s_s,(struct sockaddr*)&from, &len);
            pthread_mutex_unlock(&g_lock);    
    
            n = recv(s_c, buff, BUFFLEN,0);
            if(n > 0 && !strncmp(buff, "TIME", 4))
            {
                memset(buff, 0, BUFFLEN);
                now = time(NULL);
                sprintf(buff, "%24s
    ",ctime(&now));
                send(s_c, buff, strlen(buff),0);
            }
            close(s_c);    /*关闭客户端*/
        }
        
        return NULL;
    }
    
    static void handle_connect(int s_s)
    {    
        int s_s = s;
        pthread_t thread_do[CLIENT_NUM];
        for(int i=0; i<CLIENT_NUM;++i)
        {
            int err = pthread_create(&thread_do[i],NULL,handle_request,(void*)&s_s;
        }
        
        //等待线程结束
        for(int i=0; i<CLIENT_NUM;++i)
            pthread_join(thread_do[i],NULL);
    }
    
    int main(int argc, char *argv[])
    {
        int s_s;    /*服务器套接字文件描述符*/
        struct sockaddr_in local;    /*本地地址*/        
        
        s_s = socket(AF_INET, SOCK_STREAM, 0);/*建立TCP套接字*/
        
        /*初始化地址*/
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;/*AF_INET协议族*/
        local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
        local.sin_port = htons(SERVER_PORT);/*服务器端口*/
        
        /*将套接字文件描述符绑定到本地地址和端口*/
        int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
        err = listen(s_s, BACKLOG);/*侦听*/
            
        handle_connect(s_s);/*处理客户端连接*/
        
        close(s_s);
        
        return 0;        
    }
  • 相关阅读:
    自定义布局模板
    单据状态图
    初识MongoDB(八)
    初识MongoDB(七)
    初识MongoDB(六)
    初识MongoDB(五)
    初识MongoDB(四)
    初识MongoDB(三)
    初识MongoDB(二)
    初识MongoDB(一)
  • 原文地址:https://www.cnblogs.com/lizhenghn/p/3618986.html
Copyright © 2011-2022 走看看