Linux网络编程服务器模型选择之循环服务器

     在网络程序里面,通常都是一个服务器处理多个客户机,为了出个多个客户机的请求,服务器端的程序有不同的处理方式。本节开始介绍Linux下套接字编程的服务器模型选择,主要包括循环服务器模型、并发服务器模型、IO复用服务器模型等,这也是我们常见的几种网络服务器模型。其中基本可以分为两大类,

1. 循环服务器:循环服务器在同一时刻只能响应一个客户端的请求,是比较简单的一种模型;

2. 并发服务器:并发服务器在同一时刻可以响应多个客户端的请求,这里面又有很多分类,接下来会逐步介绍;

循环服务器模型

     循环服务器是指对于客户端的请求和连接,服务器逐个进行处理,处理完一个连接后再处理下一个连接,属于串行处理方式,结构比较简单。该模型的算法过程如下:

/* UDP循环服务器模型 */ 
 
socket(); 
 
bind(); 
 
while(true)
{
   recvfrom(); 
 
   process(); 
 
   sendto(); 
} 

close();
/* TCP循环服务器模型 */ 
 
socket(); 
 
bind(); 
 
listen(); 
 
while(true) 
{ 
 
    accept(); 
 
    while(true) 
    { 
        recv(); 
 
        process(); 
 
        send(); 
    } 
 
    close(); 
}

从上面的的流程可以看出,TCP循环服务器比UDP循环服务器多了一个accept的过程,这也是TCP和UDP套接字编程的主要区别。TCP服务器在accept出等待客户端的到来,因为accept函数是阻塞的,因此TCP服务器会在此等待(对accept函数的不同处理是区分各类服务器的一个重要参考依据)。相应地,UDP会在recvfrom阻塞,并等待客户端的连接。

一个循环服务器的例子

下面给出一个简单的循环服务器样子,模拟服务器对外提供时间服务器,等待客户端到来,并返回给客户端服务器的当前时间。

UDP循环服务器

 1 /** UDP循环服务器--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 12345
10 int main(int argc, char *argv[])
11 {

12     int s;    //服务器套接字文件描述符
13     struct sockaddr_in local, to;    //本地地址
14     time_t now;        //时间
15     char buff[BUFFLEN];//收发数据缓冲区
16     int n = 0;
17     int len = sizeof(to);
18     
19     //建立UDP套接字
20     s = socket(AF_INET, SOCK_DGRAM, 0);
21     
22     //初始化地址
23     memset(&local, 0, sizeof(local));
24     local.sin_family = AF_INET;//AF_INET协议族
25     local.sin_addr.s_addr = htonl(INADDR_ANY);//任意本地地址
26     local.sin_port = htons(SERVER_PORT);//服务器端口
27     
28     //将套接字文件描述符绑定到本地地址和端口
29     int err = bind(s, (struct sockaddr*)&local, sizeof(local));
30     
31     //主处理过程
32     while(1)
33     {
34         memset(buff, 0, BUFFLEN);
35         n = recvfrom(s, buff, BUFFLEN,0,(struct sockaddr*)&to, &len);//接收发送方数据
36         if(n > 0 && !strncmp(buff, "TIME", 4))//判断是否合法接收数据
37         {
38             printf("Get One Client Connect\n");
39             memset(buff, 0, BUFFLEN);
40             now = time(NULL);
41             sprintf(buff, "%24s\r\n",ctime(&now));
42             sendto(s, buff, strlen(buff),0, (struct sockaddr*)&to, len);//发送数据
43         }
44     }
45     close(s);
46     
47     return 0;        
48 }
View Code
 1 /** UDP循环服务器--client端程序**/
 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 12345
10 int main(int argc, char *argv[])
11 {
12     int s;    //服务器套接字文件描述符
13     struct sockaddr_in server;    //本地地址
14     time_t now;         
15     char buff[BUFFLEN]; 
16     int n = 0;     
17     int len = 0;    //地址长度
18     
19     //建立UDP套接字
20     s = socket(AF_INET, SOCK_DGRAM, 0);
21     
22     //初始化地址接 
23     memset(&server, 0, sizeof(server));
24     server.sin_family = AF_INET;//AF_INET协议族
25     server.sin_addr.s_addr = htonl(INADDR_ANY);//任意本地地址
26     server.sin_port = htons(SERVER_PORT);//服务器端口
27     
28     memset(buff, 0, BUFFLEN); 
29     strcpy(buff, "TIME"); 
30     //发送数据
31     sendto(s, buff, strlen(buff), 0, (struct sockaddr*)&server, sizeof(server));
32     memset(buff, 0, BUFFLEN);
33     //接收数据
34     len = sizeof(server);
35     n = recvfrom(s, buff, BUFFLEN, 0, (struct sockaddr*)&server, &len);
36     if(n >0)
37         printf("TIME:%s",buff);    
38     
39     close(s);
40     
41     return 0;        
42 }
View Code

  

TCP循环服务器

 1 /** TCP循环服务器--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 12346
10 #define BACKLOG 5
11 int main(int argc, char *argv[])
12 {
13     int s_s, s_c;    /*服务器套接字文件描述符*/
14     struct sockaddr_in local, from;    /*本地地址*/
15     time_t now;        
16     char buff[BUFFLEN];
17     int n = 0;
18     int len = sizeof(from);
19     
20     /*建立TCP套接字*/
21     s_s = socket(AF_INET, SOCK_STREAM, 0);
22     
23     /*初始化地址*/
24     memset(&local, 0, sizeof(local));
25     local.sin_family = AF_INET;/*AF_INET协议族*/
26     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
27     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
28     
29     /*将套接字文件描述符绑定到本地地址和端口*/
30     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
31     err = listen(s_s, BACKLOG);/*侦听*/
32     
33     /*主处理过程*/
34     while(1)
35     {
36         /*接收客户端连接*/
37         s_c = accept(s_s, (struct sockaddr*)&from, &len);
38         memset(buff, 0, BUFFLEN);
39         n = recv(s_c, buff, BUFFLEN,0);/*接收发送方数据*/
40         if(n > 0 && !strncmp(buff, "TIME", 4))/*判断是否合法接收数据*/
41         {
42             memset(buff, 0, BUFFLEN);
43             now = time(NULL);
44             sprintf(buff, "%24s\r\n",ctime(&now));
45             send(s_c, buff, strlen(buff),0);/*发送数据*/
46         }
47         close(s_c);
48     }
49     close(s_s);
50     
51     return 0;        
52 }
View Code 
/**TCP循环服务器--client端程序**/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdio.h>

#define BUFFLEN 1024
#define SERVER_PORT 12346
int main(int argc, char *argv[])
{
    int s;    /*服务器套接字文件描述符*/
    struct sockaddr_in server;    /*本地地址*/
    char buff[BUFFLEN];
    int n = 0;    
    
    /*建立TCP套接字*/
    s = socket(AF_INET, SOCK_STREAM, 0);
    
    /*初始化地址*/
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;/*AF_INET协议族*/
    server.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
    server.sin_port = htons(SERVER_PORT);/*服务器端口*/    
    
    /*连接服务器*/
    int err = connect(s, (struct sockaddr*)&server,sizeof(server));
    memset(buff, 0, BUFFLEN);
    strcpy(buff, "TIME");
    /*发送数据*/
    send(s, buff, strlen(buff), 0);
    memset(buff, 0, BUFFLEN);
    /*接收数据*/    
    n = recv(s, buff, BUFFLEN, 0);
    if(n >0){
        printf("TIME:%s",buff);    
    }
    close(s);
    
    return 0;        
}
View Code

 

两者返回给客户端的的输出都是一样的,比如:TIME:Sat Mar 22 15:26:25 2014

 

循环服务器的介绍就到这里。接下来介绍并发服务器模型。

Linux网络编程服务器模型选择之循环服务器,古老的榕树,5-wow.com

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。