您的位置:首页 > 理论基础 > 计算机网络

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

2017-10-09 14:23 567 查看
转载: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 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 }




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&g
15445
t;
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 }


  

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 }


 



/**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;
}


 
两者返回给客户端的的输出都是一样的,比如:TIME:Sat Mar 22 15:26:25 2014
 
循环服务器的介绍就到这里。接下来介绍并发服务器模型。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: