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

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

在前面我们介绍了循环服务器,并发服务器模型。简单的循环服务器每次只能处理一个请求,即处理的请求是串行的,效率过低;并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求。但是当客户端增加时,就需要创建更多的进程或者线程,就会导致系统负载最终转移到进程或线程的切换开销上。

      为了减少这类开销,而使系统处理能力集中在核心业务上,就要求我们降低并发的进程或线程数目,因此又实现了一个更高级的IO复用循环服务器。I/O复用的循环服务器一般创建两个线程,一个是客户端连接处理线程,专门用来处理客户端的连接,当有客户端到来的时候,此线程把客户端的套接字描述符放到一块公共的区域中。另一个是业务处理线程,此线程轮循(select)客户端套接字描述符集合中有没有数据到来,如果有数据到来,那么就进行处理。这样,客户 端的增加并不会造成系统进程或线程数的明显增加,而使其处理能力与CPU和内存直接相关。

TCP并发服务器模型 I/O多路复用模型伪代码

复制代码
/* TCP并发服务器模型 I/O多路复用 */  
/* 服务器主进程 */socket();bind();listen();      pthread_create( ); //创建客户端连接线程和业务处理线程pthread_join( ); //等待线程结束close( ); //关闭服务器套接字  
/* 连接处理线程 */while(1){accept( ); //接受一个客户端连接store();//存储客户端套接字描述符到一个公共集合中
  }/* 业务处理线程 */while(1){get( ); //取出可用的客户端套接字描述符select( ); //设置监听读写文件描述符集合
      recv( );process( );send( );close( );}
复制代码

一个I/O多路复用模型的例子

复制代码
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/select.h>
#define BUFFLEN 1024
#define SERVER_PORT 12349
#define BACKLOG 5  
#define CLIENTNUM 1024 /**最大支持客户端数量*//*可连接客户端的文件描述符数组*/
int connect_host[CLIENTNUM];
int connect_number =  0;
static void *handle_request(void *argv)
{    time_t now;        /*时间*/char buff[BUFFLEN];/*收发数据缓冲区*/int n = 0;int maxfd = -1;/*最大侦听文件描述符*/fd_set scanfd;    /*侦听描述符集合*/struct   timeval   timeout;     /*超时*/timeout.tv_sec     =   1; /*   阻塞1秒后超时返回   */     timeout.tv_usec   =   0;     int i = 0;int err  = -1;for(;;){   /*最大文件描述符值初始化为-1*/        maxfd = -1;FD_ZERO(&scanfd);/*清零文件描述符集合*/for(i=0;i<CLIENTNUM;i++)/*将文件描述符放入集合*/{if(connect_host[i] != -1)/*合法的文件描述符*/{FD_SET(connect_host[i], &scanfd);/*放入集合*/if(maxfd <     connect_host[i])/*更新最大文件描述符值*/{maxfd = connect_host[i];}}}/*select等待*/err = select(maxfd + 1, &scanfd, NULL, NULL, &timeout) ;        switch(err){case 0:/*超时*/break;case -1:/*错误发生*/break;default:/*有可读套接字文件描述符*/if(connect_number<=0)break;for(i = 0;i<CLIENTNUM;i++){/*查找激活的文件描述符*/if(connect_host[i] != -1)if(FD_ISSET(connect_host[i],&scanfd))   {  memset(buff, 0, BUFFLEN);/*清零*/n = recv(connect_host[i], buff, BUFFLEN,0);/*接收发送方数据*/if(n > 0 && !strncmp(buff, "TIME", 4))/*判断是否合法接收数据*/{memset(buff, 0, BUFFLEN);/*清零*/now = time(NULL);/*当前时间*/sprintf(buff, "%24s\r\n",ctime(&now));/*将时间拷贝入缓冲区*/send(connect_host[i], buff, strlen(buff),0);/*发送数据*/}/*关闭客户端*/close(connect_host[i]);    /*更新文件描述符在数组中的值*/connect_host[i] = -1;connect_number --;    /*客户端计数器减1*/                                                    } }break;     }          } return NULL;
}static void *handle_connect(void *argv)
{    int s_s = *((int*)argv) ;/*获得服务器侦听套接字文件描述符*/int s_c = -1;/*连接客户端文件描述符*/struct sockaddr_in from;int len = sizeof(from);/*接收客户端连接*/for(;;){int i = 0;int s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端的请求*/printf("a client connect, from:%s\n",inet_ntoa(from.sin_addr));/*查找合适位置,将客户端的文件描述符放入*/                for(i=0;i<CLIENTNUM;i++){if(connect_host[i] == -1)/*找到*/{/*放入*/connect_host[i]= s_c;/*客户端计数器加1*/connect_number ++;/*继续轮询等待客户端连接*/break;                        }    }        }    return NULL;
}int main(int argc, char *argv[])
{int s_s;    /*服务器套接字文件描述符*/struct sockaddr_in local;    /*本地地址*/    int i = 0;memset(connect_host, -1, CLIENTNUM);/*建立TCP套接字*/s_s = socket(AF_INET, SOCK_STREAM, 0);/*初始化地址接哦股*/memset(&local, 0, 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);/*侦听*/pthread_t  thread_do[2];/*线程ID*//*创建线程处理客户端连接*/pthread_create(&thread_do[0],/*线程ID*/NULL,/*属性*/handle_connect,/*线程回调函数*/(void*)&s_s);        /*线程参数*//*创建线程处理客户端请求*/                    pthread_create(&thread_do[1],/*线程ID*/NULL,/*属性*/handle_request,/*线程回调函数*/NULL);        /*线程参数*//*等待线程结束*/for(i=0;i<2;i++)pthread_join(thread_do[i], NULL);close(s_s);return 0;        
}
复制代码

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384321.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

memcpy/memset函数的c语言实现

转载&#xff1a;http://blog.csdn.net/u011118276/article/details/46742341 1、memcpy 头文件&#xff1a;#include <string.h> 函数原型&#xff1a;void *memcpy(void *dest, const void *src, size_t n) 功能&#xff1a;将指针src指向的内存空间的n个字节复制到des…

计算机网络(一)计算机网络体系

计算机网络&#xff08;一&#xff09;计算机网络体系一、计算机网络概述概念功能组成分类二、体系结构和参考模型ISO/OSI模型物理层网络层传输层会话层表示层应用层OSI参考模型与TCP/IP参考模型OSI参考模型与TCP/IP参考模型不同5层参考模型一、计算机网络概述 概念 计算机网…

计算机网络(二)物理层

计算机网络&#xff08;二&#xff09;物理层一、通信基础物理层接口特性1.机械特性2.电气特性3.功能特性4.规程特性典型的数据通信模型三种通信方式1.单工通信2.半双工通信/双向交替通信3.全双工通信/双向同时通信数据传输方式串行传输并行传输同步传输异步传输二、数据交换方…

计算机网络(三)数据链路层

计算机网络&#xff08;三&#xff09;数据链路层1.基本概念2.功能概述3.组帧字符计数法字符填充法零比特填充法违规编码法4.差错控制检错编码奇偶校验码CRC循环冗余码纠错编码海明码流量控制停止等待协议滑动窗口协议后退N帧协议&#xff08;GBN&#xff09;选择重传协议5.介质…

计算机网络(四)网络层

计算机网络&#xff08;四&#xff09;网络层一、概述和功能TCP/IP协议栈IP数据报格式IP数据报分片二、ipv4网络地址转换&#xff08;NAT&#xff09;子网划分子网掩码ARP协议&#xff08;地址解析协议&#xff09;DHCP协议ICMP协议二、ipv6ipv4和ipv6的区别IPv6基本地址类型IP…

操作系统(一)计算机系统概述

操作系统&#xff08;一&#xff09;计算机系统概述一、操作系统的概念二、功能和目标资源的管理者向上层提供服务对硬件的扩展三、操作系统的特征并发共享虚拟异步四、操作系统的发展与分类手工操作阶段批处理阶段单道批处理系统多道批处理系统分时操作系统实时操作系统操作系…

操作系统(二)进程管理

ui 操作系统&#xff08;二&#xff09;进程管理一、进程程序和进程进程控制块&#xff08;PCB&#xff09;进程的组成进程的特征进程的状态与转换进程状态的转换进程的组织链接方式索引方式进程的控制进程的创建进程的终止进程阻塞进程唤醒进程切换进程通信共享存储消息传递管…

gethostbyname()函数说明

转载&#xff1a;http://www.cnblogs.com/cxz2009/archive/2010/11/19/1881611.html gethostbyname()函数说明——用域名或主机名获取IP地址 包含头文件 #include <netdb.h> #include <sys/socket.h> 函数原型 struct hostent *gethostbyna…

操作系统(三)内存管理

操作系统&#xff08;三&#xff09;内存管理一、程序执行过程装入的三种方式链接的三种方式二、内存管理的概念内存空间的分配与回收连续分配管理方式单一连续分配固定分区分配动态分区分配首次适应算法最佳适应算法最坏适应算法邻近适应算法非连续分配管理方式基本分页存储管…

操作系统(四)文件管理

操作系统&#xff08;四&#xff09;文件管理一、文件系统基础1.文件逻辑结构无结构文件有结构文件2.文件目录文件控制块&#xff08;FCB&#xff09;目录结构单级目录两级目录结构多级目录结构无环图目录结构3.文件保护口令保护加密保护访问控制4.文件共享硬链接软链接5.文件系…

如何在Ubuntu上安装GCC编译器

如何在Ubuntu上安装GCC编译器1.首先更新包列表sudo apt update2.安装build-essential软件包&#xff1a; sudo apt install build-essential3.验证GCC编译器是否已成功安装&#xff0c;请使用gcc --version命令打印GCC版本 rootubuntu:/home/csd# gcc --version

操作系统(五)输入/输出(I/O)管理

操作系统&#xff08;五&#xff09;输入/输出&#xff08;I/O&#xff09;管理一、I/O控制器二、I/O控制方式程序直接控制方式中断驱动方式DMA方式通道控制方式I/O软件层次结构假脱机技术设备的分配与回收缓冲区单缓冲双缓冲循环缓冲区缓冲池一、I/O控制器 I/O设备由机械部件…

Linux下的I/O多路复用select,poll,epoll浅析

转载&#xff1a;http://blog.csdn.net/u011573853/article/details/52105365 一&#xff0c;什么是I/O多路复用 所谓的I/O多路复用在英文中其实叫 I/O multiplexing. 就是单个线程&#xff0c;通过记录跟踪每个I/O流(sock)的状态&#xff0c;来同时管理多个I/O流 。) I/O mu…

计算机组成原理(一)计算机系统概述

计算机组成原理&#xff08;一&#xff09;计算机系统概述一、计算机系统层次结构冯诺伊曼机计算机工作过程多级层次结构一、计算机系统层次结构 冯诺伊曼机 特点&#xff1a; 计算机由五大部件组成指令和数据以同等地位存于存储 器&#xff0c;可按地址寻访指令和数据用二进…

计算机组成原理(二)数据的表示和运算

计算机组成原理&#xff08;二&#xff09;数据的表示和运算一、BCD码二、奇偶校验码三、海明码四、循环冗余校验码&#xff08;CRC&#xff09;五、乘法运算原码乘法补码乘法六、除法运算原码除法补码除法七、浮点数的表示与运算浮点数的运算一、BCD码 组合式BCD码&#xff1…

Linux IO复用区别与epoll详解

转载&#xff1a;http://blog.csdn.net/hacker00011000/article/details/52160590 一、select、poll、epoll之间的区别总结[整理]   select&#xff0c;poll&#xff0c;epoll都是IO多路复用的机制。I/O多路复用就通过一种机制&#xff0c;可以监视多个描述符&#xff0c;一…

简单图和多重图

一、简单图    ① 不存在重复边&#xff1b;    ② 不存在顶点到自身的边&#xff1b; 二、多重图   ① 某两结点之间边数多于一条&#xff1b;   ② 允许顶点通过一条边和自己关联&#xff1b;

C++笔记:select多路复用机制

转载&#xff1a;http://blog.csdn.net/qdx411324962/article/details/42499535 函数作用&#xff1a; 系统提供select函数来实现多路复用输入/输出模型。select系统调用是用来让我们的程序监视多个文件句柄的状态变化的。程序会停在select这里等待&#xff0c;直到被监视的文件…

交叉编译执行应用程序出现:No such file or directory

问题分析 当我在arm板子上执行交叉编译过的程序的时候发现了这个错误。通过百度查询基本都是缺少32位库什么的,但是都不能解决问题。 然后我用ll指令&#xff0c;也排除了权限的原因。 我们用ldd指令发现&#xff0c;它不是动态执行的&#xff0c;虽然我们可以使用-static指…

select、poll、epoll 比较

转载&#xff1a;http://blog.csdn.net/dodo_328/article/details/39081183 1.Selet&#xff1a;本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。 缺点&#xff1a;1 单个进程可监视的fd数量被限制&#xff0c;因为受描述符集合fd_set限制&#xff0c;fd数量…