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

来源:互联网 发布:淘宝企业店开店流程 编辑:程序博客网 时间:2024/05/29 03:03

转载:http://www.cnblogs.com/lizhenghn/p/3617608.html

在网络程序里面,通常都是一个服务器处理多个客户机,为了出个多个客户机的请求,服务器端的程序有不同的处理方式。本节开始介绍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 1234510 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 }
复制代码
复制代码
 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 1234510 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 }
复制代码

  

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 1234610 #define BACKLOG 511 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 }
复制代码
 
复制代码
/**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 12346int 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;        }
复制代码

 

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

 

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



原创粉丝点击