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

时间:2022-05-19 04:29:15

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

简单并发服务器模型

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

一个并发服务器的例子

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

UDP循环服务器

 /** UDP并发服务器--server端程序**/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#define BUFFLEN 1024
#define SERVER_PORT 12347
#define BACKLOG 5 static void handle_request(int s, struct sockaddr_in* from, char *buff)
{
time_t now;
int len = sizeof(*from);
memset(buff, , BUFFLEN);
now = time(NULL);
sprintf(buff, "%24s\r\n",ctime(&now));
sendto(s, buff, strlen(buff),, (struct sockaddr*)from, len);/*发送数据*/
} static void handle_connect(int s_s)
{
struct sockaddr_in from; /*客户端地址*/
int len = sizeof(from);
int n = ;
char buff[BUFFLEN]; /*主处理过程*/
while()
{
memset(buff, , BUFFLEN);
/*接收客户端连接*/
n = recvfrom(s_s, buff, BUFFLEN,,(struct sockaddr*)&from, &len);/*接收发送方数据*/
if(n > && !strncmp(buff, "TIME", ))/*判断是否合法接收数据*/
{
/*创建进程进行数据处理*/
if(!fork())
{
handle_request(s_s, &from, buff);/*处理连接请求*/
return ;
}
}
}
} int main(int argc, char *argv[])
{
int s_s; /*服务器套接字文件描述符*/
struct sockaddr_in local; /*本地地址*/ /*建立TCP套接字*/
s_s = socket(AF_INET, SOCK_STREAM, ); /*初始化地址接哦股*/
memset(&local, , sizeof(local));
local.sin_family = AF_INET;/*AF_INET协议族*/
local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
local.sin_port = htons(SERVER_PORT);/*服务器端口*/ /*将套接字文件描述符绑定到本地地址和端口*/
int err = bind(s_s, (struct sockaddr*)&local, sizeof(local)); /*处理客户端连接*/
handle_connect(s_s); close(s_s); return ;
}

TCP循环服务器

 /** TCP并发服务器--server端程序**/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#define BUFFLEN 1024
#define SERVER_PORT 12347
#define BACKLOG 5 static void handle_request(int s_c)
{
time_t now;
char buff[BUFFLEN];
int n = ;
memset(buff, , BUFFLEN);
n = recv(s_c, buff, BUFFLEN,);/*接收发送方数据*/
if(n > && !strncmp(buff, "TIME", ))/*判断是否合法接收数据*/
{
memset(buff, , BUFFLEN);
now = time(NULL);
sprintf(buff, "%24s\r\n",ctime(&now));
send(s_c, buff, strlen(buff),);/*发送数据*/
}
/*关闭客户端*/
close(s_c);
} static void handle_connect(int s_s)
{
int s_c; /*客户端套接字文件描述符*/
struct sockaddr_in from; /*客户端地址*/
int len = sizeof(from); /*主处理过程*/
while()
{
/*接收客户端连接*/
s_c = accept(s_s, (struct sockaddr*)&from, &len);
if(s_c > )/*客户端成功连接*/
{
/*创建进程进行数据处理*/
if(fork() > )/*父进程*/
{
close(s_c);/*关闭父进程的客户端连接套接字*/
}
else
{
handle_request(s_c);/*处理连接请求*/
return ;
}
}
}
} int main(int argc, char *argv[])
{
int s_s; /*服务器套接字文件描述符*/
struct sockaddr_in local; /*本地地址*/ /*建立TCP套接字*/
s_s = socket(AF_INET, SOCK_STREAM, ); /*初始化地址*/
memset(&local, , sizeof(local));
local.sin_family = AF_INET;/*AF_INET协议族*/
local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/
local.sin_port = htons(SERVER_PORT);/*服务器端口*/ /*将套接字文件描述符绑定到本地地址和端口*/
int err = bind(s_s, (struct sockaddr*)&local, sizeof(local));
err = listen(s_s, BACKLOG);/*侦听*/ /*处理客户端连接*/
handle_connect(s_s); close(s_s); return ;
}

注意,

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

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

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

Linux网络编程服务器模型选择之并发服务器(上)的更多相关文章

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

    前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率较低,同一时刻只能为一个客户端提供服务,而且对于TCP模型来说,还存在单客户端长久独占与服务器的连接, ...

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

    在网络程序里面,通常都是一个服务器处理多个客户机,为了出个多个客户机的请求,服务器端的程序有不同的处理方式.本节开始介绍Linux下套接字编程的服务器模型选择,主要包括循环服务器模型.并发服务器模型. ...

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

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

  4. Linux网络编程&lpar;简单的时间获取服务器&rpar;

    1.一个简单的服务器时间获取程序 服务器和客户端采用UDP通信的方式,来编写一个简单的时间获取应用. 把过程大致理顺一下,首先是服务器端的编写,使用的是迭代的方式,没有并发 先创建一个socket而后 ...

  5. linux网络编程学习笔记之五 -----并发机制与线程�

    进程线程分配方式 简述下常见的进程和线程分配方式:(好吧,我仅仅是举几个样例作为笔记...并发的水太深了,不敢妄谈...) 1.进程线程预分配 简言之,当I/O开销大于计算开销且并发量较大时,为了节省 ...

  6. Linux网络编程&lpar;二&rpar;

    Linux网络编程(二) 使用多进程实现服务器并发访问. 采用多进程的方式实现服务器的并发访问的经典范例. 程序实现功能: 1.客户端从标准输入读入一行文字,发送到服务器. 2.服务器接收到客户端发来 ...

  7. Linux网络编程——tcp并发服务器(poll实现)

    想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程——I/O复用之poll函数> 代码: #include <string.h> #include <st ...

  8. 服务器编程入门(4)Linux网络编程基础API

      问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字( ...

  9. Linux 高性能服务器编程——Linux网络编程基础API

    问题聚焦:     这节介绍的不仅是网络编程的几个API     更重要的是,探讨了Linux网络编程基础API与内核中TCP/IP协议族之间的关系.     这节主要介绍三个方面的内容:套接字(so ...

随机推荐

  1. IE 浏览器各个版本 JavaScript 支持情况一览表

    语言元素 语言元素 突发.IE6 标准.IE7 标准 IE8 标准 IE 9 标准 IE 10 标准 边缘 Windows 应用商店应用程序 __proto__ 属性 (Object) (JavaSc ...

  2. C&num;添加测量运行时间

    使用范围 使用模块化开发,每个模块都有初始化功能,初始化功能可能包括:加载配置表,初始化事件,初始化设置 那么如果想测量每个模块的Init时间呢?Net框架已经提供了测量运行的方法 System.Di ...

  3. C&num;微信公众号开发系列教程五(接收事件推送与消息排重)

    微信公众号开发系列教程一(调试环境部署) 微信公众号开发系列教程一(调试环境部署续:vs远程调试) C#微信公众号开发系列教程二(新手接入指南) C#微信公众号开发系列教程三(消息体签名及加解密) C ...

  4. springMVC-mvc&colon;annotation-driven

    <mvc:annotation-driven/>会自动注册 RequestMappingHandlerMapping RequestMappingHandlerAdapter Except ...

  5. CentOS7 安装 mongodb

    https://docs.mongodb.com/manual/tutorial/install-mongodb-enterprise-on-red-hat/

  6. nginx 环境搭建(基于linux)

    Nginx是一种服务器软件,故而其最主要.最基本的功能当然是可以与服务器硬件结合,让程序员可以将程序放在Nginx服务器上,将程序发布出去,让成千上万的网民可以浏览.除此之外,Nginx是一种高性能的 ...

  7. &lbrack;百度空间&rsqb; &lbrack;转&rsqb; 在 Visual C&plus;&plus; 中控制全局对象的初始化顺序

    from: http://blog.csdn.net/classfactory/archive/2004/08/07/68202.aspx 在 C++ 中,同一个翻译单位(.cpp文件)里的全局对象的 ...

  8. 模块化写法-IIFE解析

    一.IIFE解释 全拼Imdiately Invoked Function Expression,立即执行的函数表达式.  像如下的代码所示,就是一个匿名立即执行函数: (function(windo ...

  9. SmartSql 常见问题

    常见问题 为什么不支持 Linq? SmartSql 希望 开发人员更多的接触 Sql ,获得绝对的控制权与安全感.所以目前没有计划支持 Code First 编程模式. 我想好了Sql怎么写,然后再 ...

  10. (十三)事件分发器——event&lpar;&rpar;函数,事件过滤

    事件分发器——event()函数 事件过滤 事件进入窗口之前被拦截 eventFilter #include "mywidget.h" #include "ui_mywi ...