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)