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

与循环服务器的串行处理不同,并发服务器对服务请求并发处理。循环服务器只能够一个一个的处理客户端的请求,显然效率很低。并发服务器通过建立多个子进程来实现对请求的并发处理。并发服务器的一个难点是如何确定子进程的数据,因为不清楚请求客户端的数目,因此实现中通常采用事先分配一定数目的子进程与动态增加子进程相结合的方法来实现并发服务器。

简单并发服务器模型

/* UDP简单并发服务器模型 */
/* 服务器主进程 */
socket(...);
bind(...);
fork(); //创建多个子进程进行请求处理
while(1);
/* 服务器子进程1 */
while(1)
{recvfrom(....);process(...);sendto(.....);
}
close(...);
/* 服务器子进程2(同上) */
..................
..................
..................
/* 服务器子进程3(同上) */
..................
..................
..................
/* TCP简单并发服务器模型 */
/* 服务器主进程 */
socket(...);
bind(...);
fork();//创建多个子进程进行请求处理
while(1);
/* 服务器子进程1 */
socket(...);
bind(...);
listen(...);
while(1)
{accept(...);recv(....)process(...);send(.....);
}
close(....);
/* 服务器子进程2(同上) */
..................
..................
..................
/* 服务器子进程3(同上) */
..................
..................
..................

一个并发服务器的例子

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

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 12347
10 #define BACKLOG 5
11
12 static void handle_request(int s, struct sockaddr_in* from, char *buff)
13 {
14     time_t now;
15     int len = sizeof(*from);
16     memset(buff, 0, BUFFLEN);
17     now = time(NULL);
18     sprintf(buff, "%24s\r\n",ctime(&now));
19     sendto(s, buff, strlen(buff),0, (struct sockaddr*)from, len);/*发送数据*/
20 }
21
22 static void handle_connect(int s_s)
23 {
24     struct sockaddr_in from;    /*客户端地址*/
25     int len = sizeof(from);
26     int n = 0;
27     char buff[BUFFLEN];
28
29     /*主处理过程*/
30     while(1)
31     {
32         memset(buff, 0, BUFFLEN);
33         /*接收客户端连接*/
34         n = recvfrom(s_s, buff, BUFFLEN,0,(struct sockaddr*)&from, &len);/*接收发送方数据*/
35         if(n > 0 && !strncmp(buff, "TIME", 4))/*判断是否合法接收数据*/
36         {
37             /*创建进程进行数据处理*/
38             if(!fork())
39             {
40                 handle_request(s_s, &from, buff);/*处理连接请求*/
41                 return ;
42             }
43         }
44     }
45 }
46
47
48 int main(int argc, char *argv[])
49 {
50     int s_s;    /*服务器套接字文件描述符*/
51     struct sockaddr_in local;    /*本地地址*/
52
53     /*建立TCP套接字*/
54     s_s = socket(AF_INET, SOCK_STREAM, 0);
55
56     /*初始化地址接哦股*/
57     memset(&local, 0, sizeof(local));
58     local.sin_family = AF_INET;/*AF_INET协议族*/
59     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
60     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
61
62     /*将套接字文件描述符绑定到本地地址和端口*/
63     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
64
65     /*处理客户端连接*/
66     handle_connect(s_s);
67
68     close(s_s);
69
70     return 0;
71 }

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 12347
10 #define BACKLOG 5
11
12 static void handle_request(int s_c)
13 {
14     time_t now;
15     char buff[BUFFLEN];
16     int n = 0;
17     memset(buff, 0, BUFFLEN);
18     n = recv(s_c, buff, BUFFLEN,0);/*接收发送方数据*/
19     if(n > 0 && !strncmp(buff, "TIME", 4))/*判断是否合法接收数据*/
20     {
21         memset(buff, 0, BUFFLEN);
22         now = time(NULL);
23         sprintf(buff, "%24s\r\n",ctime(&now));
24         send(s_c, buff, strlen(buff),0);/*发送数据*/
25     }
26     /*关闭客户端*/
27     close(s_c);
28 }
29
30 static void handle_connect(int s_s)
31 {
32     int s_c;    /*客户端套接字文件描述符*/
33     struct sockaddr_in from;    /*客户端地址*/
34     int len = sizeof(from);
35
36     /*主处理过程*/
37     while(1)
38     {
39         /*接收客户端连接*/
40         s_c = accept(s_s, (struct sockaddr*)&from, &len);
41         if(s_c > 0)/*客户端成功连接*/
42         {
43             /*创建进程进行数据处理*/
44             if(fork() > 0)/*父进程*/
45             {
46                 close(s_c);/*关闭父进程的客户端连接套接字*/
47             }
48             else
49             {
50                 handle_request(s_c);/*处理连接请求*/
51                 return ;
52             }
53         }
54     }
55 }
56
57
58 int main(int argc, char *argv[])
59 {
60     int s_s;    /*服务器套接字文件描述符*/
61     struct sockaddr_in local;    /*本地地址*/
62
63     /*建立TCP套接字*/
64     s_s = socket(AF_INET, SOCK_STREAM, 0);
65
66     /*初始化地址*/
67     memset(&local, 0, sizeof(local));
68     local.sin_family = AF_INET;/*AF_INET协议族*/
69     local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
70     local.sin_port = htons(SERVER_PORT);/*服务器端口*/
71
72     /*将套接字文件描述符绑定到本地地址和端口*/
73     int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
74     err = listen(s_s, BACKLOG);/*侦听*/
75
76     /*处理客户端连接*/
77     handle_connect(s_s);
78
79     close(s_s);
80
81     return 0;
82 }

注意,

1. 为了方便退出,server程序中对信号SIGINT信号进行了处理,此时所有的进程都会退出;

2. 并发服务器中的client程序与上一节介绍循环服务器时使用的client程序是一样的,这里不在贴出来,

请参考 Linux网络编程服务器模型选择之循环服务器 http://www.cnblogs.com/lizhenghn/p/3617608.html

Linux网络编程服务器模型选择之并发服务器(上)相关推荐

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

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

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

    转载:http://www.cnblogs.com/lizhenghn/p/3617608.html 在网络程序里面,通常都是一个服务器处理多个客户机,为了出个多个客户机的请求,服务器端的程序有不同的 ...

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

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

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

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

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

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

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

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

  7. 【Linux网络编程部分----多进程高并发poll模型】

    目录 前言 背景 分析 编写步骤 服务器: 客户端: 服务器端代码 附:文件操作部分 附:目录操作部分 客户端代码 全部代码 头文件部分 服务器全部代码 客户端所有代码 总结: 前言 本文采用  Vi ...

  8. Linux网络编程基础及多线程并发案例

    目录 1.ip:端口  TCP/IP协议 2.socket 头文件  sys/socket.h 3.字节序 4.ip地址转换函数 5.sockaddr和sockaddr_in 6.服务器端基本函数 b ...

  9. Linux网络编程学习笔记

    声明:1.未经过原作者许可,不可用于商业行为:2.本笔记仅用于知识学习,如有侵权,立即删除. 1.学习链接 黑马程序员-Linux网络编程:https://www.bilibili.com/video ...

最新文章

  1. 插件化知识梳理(7) 类的动态加载入门
  2. 文件管理系统_我的文件管理系统
  3. ALV面向对象方法研究:添加自定义工具栏(三)
  4. 报表-对于多数据进行 分sheet以及 分workbook处理
  5. 【已完结!】Java基础--学习笔记(零起点打开java世界的大门)--博客汇总表【附:视频、工程源码、资料、详细笔记】
  6. QTP:General Error while saving the test 的解决方法
  7. 潘石屹也要学编程了?Python之父:并非人人都需要了解计算机发生了什么
  8. 7-110 自动售货机 (30 分)
  9. Coursera学科分类爬虫实例介绍
  10. 中国智能座舱行业发展前景展望与投资战略规划研究报告2022年版
  11. python根据题库答案自动答题_直播答题助手 自动检测出题、搜索答案
  12. editormd编辑器在flask中的使用
  13. redhat 8常用命令实践
  14. 2021年2月28日【Jiawei_Z】Ethercat的整个实现过程(举例:Lan9252)
  15. linux国际象棋,国际象棋通用引擎协议
  16. JAVA 启动JVM时,Xms和Xmx参数
  17. 一个语法分析器的实现
  18. 移动WEB开发之响应式布局--Bootstrap栅格系统
  19. openwrt怎么做ap_终于把无线AP鸡肋的系统刷成openwrt,从此山鸡变凤凰!
  20. jqGrid可编辑模式下 单元格内容不能复制处理

热门文章

  1. mysql启动错误排查-无法申请足够内存
  2. C#反射Assembly 具体说明
  3. 硬件信息修改大师_零成本学习之单片机硬件开发(1)
  4. tps波动很大的原因_花生价格小幅上涨,要突破6元大关?粮贩:还有很大距离...
  5. mysql断开同步并记录位置_数据库同步自动断开问题的处理
  6. postman使用_postman如何使用集合断言?
  7. Java字符与数字的计算
  8. 靶场练习第十天~vulnhub靶场之dc-2
  9. Win32ASM学习[20]:子程序
  10. 160 - 32 genocide1