转载: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>
 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

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

Linux网络编程服务器模型选择之循环服务器相关推荐

  1. Linux网络编程服务器模型选择之并发服务器(上)

    转载:http://www.cnblogs.com/lizhenghn/p/3617666.html 与循环服务器的串行处理不同,并发服务器对服务请求并发处理.循环服务器只能够一个一个的处理客户端的请 ...

  2. Linux网络编程服务器模型选择之并发服务器(下)

    转载:http://www.cnblogs.com/lizhenghn/p/3618986.html 前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率 ...

  3. Linux网络编程服务器模型选择之IO复用循环并发服务器

    在前面我们介绍了循环服务器,并发服务器模型.简单的循环服务器每次只能处理一个请求,即处理的请求是串行的,效率过低:并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求.但是当客户端增加时,就需 ...

  4. linux网络编程-多线程实现TCP并发服务器

    客户端跟服务端通信流程 服务端流程步骤 socket函数创建监听套接字lfd; bind函数将监听套接字绑定ip和端口: listen函数将服务器设置为被动监听状态,同时创建一条未完成连接队列(没走完 ...

  5. 第4章 Linux网络编程 22.多进程实现并发服务器、多线程实现并发服务器

    目录 多线程实现并发服务器 多进程实现并发服务器 多线程实现并发服务器 server_thread.c #include <stdio.h> #include <arpa/inet. ...

  6. Linux网络编程基础<多进程并发服务器>

    一.应用场景 最简单的socket示列代码只能一个客户端连接一个服务器,并不支持多个客户端对服务器的连接,为了能让多个客户端进行连接所以需要多进程或者多线程处理 二.思路解析 服务器端的程序是俩个套接 ...

  7. 【Linux网络编程】循环服务器之TCP模型

    00. 目录 文章目录 00. 目录 01. 概述 02. TCP循环服务器实现方法 03. TCP循环服务器模型 04. TCP循环服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按使 ...

  8. 【Linux网络编程】循环服务器之UDP循环模型

    00. 目录 文章目录 00. 目录 01. 概述 02. UDP循环服务器的实现方法 03. UDP循环服务器模型 04. UDP循环服务器实现 05. 附录 01. 概述 服务器设计技术有很多,按 ...

  9. 【Linux】Linux网络编程(含常见服务器模型,下篇)

    上一篇文章:[Linux]Linux网络编程(含常见服务器模型,上篇). 高级嵌套字函数 前面介绍的一些函数(read.write等)都是网络程序里最基本的函数,也是最原始的通信函数.下面介绍一下几个 ...

最新文章

  1. mysql自动增长恢复_mysql自动增长的有关问题,怎么恢复从1开始
  2. MPLS QoS的实现——微云专线
  3. appium(3)-Running Tests
  4. 简单C语言程序的执行过程
  5. Excel2007导入
  6. [转载]AngularJS之Factory vs Service vs Provider
  7. 监督学习 | 集成学习 之Bagging、随机森林及Sklearn实现
  8. java理论之java基础
  9. 阅读bulid to win感想
  10. 作为一个职场中人的一些思考,关于做事的方式和思路
  11. 传统企业如何面对电子商务的发展
  12. C++ 字符串和数字拼接
  13. A Linux Environment Zero Overhead
  14. 极路由4增强版刷OpenWrt折腾系列
  15. Appium:无法启动应该,报错: Moving to state ‘stopped‘
  16. 动态规划-最少硬币组合问题(Java)
  17. 瓢城旅行社网页界面设计(HTML+CSS)
  18. MATLAB——IIR数字滤波器的设计
  19. 用python表白代码_python浪漫表白源码
  20. 给初学Java的老铁,知道这4点太重要了!

热门文章

  1. Linux/CentOS7install PackageError: Loaded plugins: fastestmirror
  2. linux常用命令大全(转)好东西要分享
  3. 20145335郝昊《网络攻防》Bof逆向基础——ShellCode注入与执行
  4. 如何搭建lamp(CentOS7+Apache+MySQL+PHP)环境 [转]
  5. JavascriptDOM(三)
  6. 基于RBAC模型的通用企业权限管理系统
  7. argmax函数_1.4 TensorFlow2.1常用函数
  8. 乐高无限的服务器怎么建,乐高无限悬空房子怎么建造 建造方法介绍
  9. form字体和颜色java安卓开发_Android 修改App中默认TextView的字体和颜色
  10. 常见问题_智能切膜机常见问题