Linux编程基础 8.3:I/O多路转接服务器

1 简介

为进一步提升服务器效率,人们提出了一种被称为I/O多路转接的模型。其中“多路”指代连接到服务器的多个客户端程序,而“转接”则是指在服务器主线与各分支之间设置一个“岗位”,由该岗位实现监控多路连接中数据状态的功能,若某路连接中数据就绪,就通知服务器,使主程序对该路请求作出处理。
与多进程和多线程并发服务器相比,I/O多路转接服务器实现了I/O多路复用,系统不必创建多进程或多线程,也不必维护多个进程或线程,因此大大降低了系统开销。
Linux系统实现I/O多路转接函数有:

  • select()
  • poll()
  • epoll()

2 select函数

在这里插入图片描述
图 select通信模型示意图

  • 使用select搭建的I/O多路转接服务器是一种基于非阻塞的服务器;
  • 当有客户端连接请求到达时,accept会返回一个文件描述符,该文件描述符会被存储到由select监控的文件描述符表中,每个文件描述符对应的文件都可进行I/O操作,因此select可通过监控表中各个文件描述符,来获取对应的客户端I/O状态。
  • 若每路程序中都没有数据到达,线程将阻塞在select上;否则select将已就绪客户端程序的数量返回到服务器。
#include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);
struct timeval{long tv_sec;long tv_user;
};

功能: 监视客户端I/O接口的状态
参数说明:

  • nfds:设置select监控的文件描述符的范围,需设置为文件描述符最大值加1;
  • readfds:可读取数据的文件描述符集,fd_set实质为长整型,这些集合中的每一位都对应一个文件描述符的状态;若集合参数被设置为NULL,表示不关心文件的对应状态;
  • writefds:可写入数据的文件描述符集;
  • exceptfds:发生异常的文件描述符集;
  • timeout:设置select的阻塞时长,其取值有如下几种情况:
    – 若timeval=NULL,表示永远等待;
    – 若timeval>0,表示等待固定时长;
    – 若timeval=0,select将在检查过指定文件描述符后立即返回(轮询)。

Linux系统提供了一系列操作文件描述符集的函数:

函数声明函数功能
void FD_CLR(int fd,fd_set *set);将集合中的文件描述符fd清除(将fd位置为0)
int FD_ISSET(int fd,fd_set *set);测试集合中文件描述符fd是否存在于集合中,若存在则返回非0
void FD_SET(int fd,fd_set *set);将文件描述符fd添加到集合中(将fd位置为1)
void FD_ZERO(fd_set *set);清除集合中所有的文件描述符(所有位置0)

返回值说明:

  • 大于0:表示已就绪文件描述符的数量,此种情况下某些文件可读写或有错误信息;
  • 等于0:表示等待超时,没有可读写或错误的文件;
  • -1:表示出错返回,同时errno将被设置。

特别说明:

  • select可监控的进程数量是有限的,该数量受到两个因素的限制。
    –第一个因素是进程可打开的文件数量;
    –第二个因素是select中的集合fd_set的容量。
  • 进程可打开文件的上限可通过ulimit –n命令或setrlimit函数设置,但系统所能打开的最大文件数也是有限的;
  • select中集合fd_set的容量由宏FD_SETSIZE(定义在linux/posix_types.h中)指定;
  • 即便通过重新编译内核的方式修改FD_SETSIZE,也不一定能提升select服务器的性能,因为若select一次监测的进程过多,单轮询便要耗费大量的时间。

【案例 1】使用select模型搭建多路I/O转接服务器。

  • 服务器:接收客户端数据,并将接收到的数据转为大写,写回客户端;
  • 客户端:向服务器发送数据,并将服务器返回的数据打印到终端。
selectClient.c
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"
#define MAXLINE 80					//缓冲数组大小
#define SERV_PORT 8000				//端口号
int main() {struct sockaddr_in tempServAddr;char tempBuf[MAXLINE];int tempSockFd, tempDataLen;tempSockFd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&tempServAddr, sizeof(tempServAddr));tempServAddr.sin_family = AF_INET;inet_pton(AF_INET, "127.0.0.1", &tempServAddr.sin_addr);tempServAddr.sin_port = htons(SERV_PORT);Connect(tempSockFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));while (fgets(tempBuf, MAXLINE, stdin) != NULL) {Write(tempSockFd, tempBuf, strlen(tempBuf));tempDataLen = Read(tempSockFd, tempBuf, MAXLINE);if (tempDataLen == 0){printf("the other side has been closed.\n");} else {Write(STDOUT_FILENO, buf, n);}//of if}//of whileClose(sockfd);return 0;
}//of mainselectServer.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "wrap.h"
#define MAXLINE 80						//缓冲数组大小
#define SERV_PORT 8000					//端口号
int main() {int i, tempMaxI, tempMaxFd, tempListenFd, tempConnFd, tempSockFd;int tempNReady, tempClient[FD_SETSIZE]; 	//FD_SETSIZE 默认为1024ssize_t tempDataLen;fd_set tempRset, tempAllset;char tempBuf[MAXLINE];char tempStr[INET_ADDRSTRLEN];			//#define INET_ADDRSTRLEN 16socklen_t tempCliAddrLen;struct sockaddr_in tempCliAddr, tempServAddr;tempListenFd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&tempServAddr, sizeof(tempServAddr));tempServAddr.sin_family = AF_INET;tempServAddr.sin_addr.s_addr = htonl(INADDR_ANY);tempServAddr.sin_port = htons(SERV_PORT);Bind(tempListenFd, (struct sockaddr *)&tempServAddr, sizeof(tempServAddr));Listen(tempListenFd, 20);		//默认最大128tempMaxFd = tempListenFd;tempMaxI = -1;//初始化监控列表for (i = 0; i < FD_SETSIZE; i++){tempClient[i] = -1; 	//使用-1初始化client[]中元素}//of for iFD_ZERO(&tempAllset);FD_SET(tempListenFd, &tempAllset); 	//将listenfd添加到文件描述符集中//循环监测处于连接状态进程的文件描述符for (;;) {//使用变量rset获取文件描述符集合tempRset = tempAllset;//记录就绪进程数量tempNReady = select(tempMaxFd + 1, &tempRset, NULL, NULL, NULL);if (tempNReady < 0){perr_exit("select error");}//of ifif (FD_ISSET(tempListenFd, &tempRset)){//有新连接请求到达则进行连接便处理连接请求tempCliAddrLen = sizeof(tempCliAddr);tempConnFd = Accept(tempListenFd, (struct sockaddr *)&tempCliAddr, &tempCliAddrLen);printf("received from %s at PORT %d\n",inet_ntop(AF_INET, &tempCliAddr.sin_addr, tempStr, sizeof(tempStr)), ntohs(tempCliAddr.sin_port));for (i = 0; i < FD_SETSIZE; i++){if (tempClient[i] < 0) {tempClient[i] = tempConnFd ; 	//将文件描述符connfd保存到client[]中break;}//of if}//of for iif (i == FD_SETSIZE) { 		//判断连接数是否已达上限fputs("too many clients\n", stderr);exit(1);}//of ifFD_SET(tempConnFd, &tempAllset); 	//添加新文件描述符到监控信号集中if (tempConnFd > tempMaxFd) {		//更新最大文件描述符tempMaxFd = tempConnFd;}//of ifif (i > tempMaxI) {				//更新client[]最大下标值tempMaxI = i;}//of if//若无文件描述符就绪,便返回select,继续阻塞监测剩余的文件描述符if (--tempNReady == 0){continue;}//of if}//of if//遍历文件描述符集,处理已就绪的文件描述符for (i = 0; i <= tempMaxI; i++) {if ((tempSockFd = tempClient[i]) < 0){continue;}//of ifif (FD_ISSET(tempSockFd, &tempRset)) {//n=0,client就绪但未读到数据,表示client将关闭连接if ((tempDataLen = Read(tempSockFd, tempBuf, MAXLINE)) == 0) {//关闭服务器端连接Close(tempSockFd);FD_CLR(tempSockFd, &tempAllset); //清除集合中对应的文件描述符tempClient[i] = -1;} else {//处理获取的数据int j;for (j = 0; j < tempDataLen; j++){tempBuf[j] = toupper(tempBuf[j]);}//of for jWrite(sockfd, buf, tempDataLen);}//of ifif (--tempNReady == 0){break;}//of if}//of if}//of for i}//of forClose(tempListenFd);return 0;
}//of main

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

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

相关文章

测井储层参数预测+人工智能方法

1 问题描述 测井储层参数预测 地层泥质含量&#xff1b;地层孔隙度&#xff08;POR&#xff09;&#xff1b;含水饱和度&#xff08;SW&#xff09;&#xff1b;渗透率&#xff08;PERM&#xff09;。 输入&#xff1a;声波时差&#xff08;AC&#xff09;、补偿中子&#x…

windows 安装openssh服务端_Git神器| SourceTree安装使用教程

SourceTree 是 Windows 和Mac OS X 下免费的Git客户端管理工具。支持创建、克隆、提交、push、pull 和合并等操作。一、sourcetree的安装1. 下载sourcetree下载链接&#xff1a;Sourcetree | Free Git GUI for Mac and Windows2. 安装sourcetree点击安装&#xff0c;第一个创建…

中国大学生计算机设计大赛--软件应用与开发类--经验总结

1 大赛介绍 中国大学生计算机设计大赛是我国高校面向本科生最早的赛事之一&#xff0c;自2008年开赛至2019年&#xff0c;一直由教育部高校与计算机相关教指委等或独立或联合主办。此赛目前是全国普通高校大学生竞赛排行榜榜单赛事之一。 我们参加了很多届大赛&#xff0c;在2…

网络与系统安全1.1 中间人攻击

1 Diffie-Hellman密钥交换过程 2 中间人攻击过程

centos 安装jdk_centos7配置jdk

一、查看centos7是否有自带jdk查看是否安装过java rpm -qa | grep java 如果是centos 一般会自带两个openjdk rpm -e --nodeps 要卸载的包 (包通过上面的指令可以获取到)] 将显示java的包全都卸载 命令&#xff1a; rpm -e --nodeps 要卸载的包二、创建/opt/app目录,用于安装JD…

隐私计算 1 隐私计算的定义与背景

1 隐私计算的定义 隐私计算&#xff1a;在保证数据提供方不泄露原始数据的前提下&#xff0c;对数据进行分析计算的一系列技术&#xff0c;保障数据在流通和融合过程中“可用不可见”。 隐私计算涉及到的学科&#xff1a; 密码学&#xff1b;统计学&#xff1b;计算机体系结…

php object 对象不存在。增加对象_PHP核心

1、单例模式单例模式三要素&#xff1a;拥有一个构造函数&#xff0c;并且为private拥有一个静态成员变量来保持类的实例拥有一个访问这个实例的静态方法<?php //Instan.php 单例类class Instan{static public $instance null;private function __construct(){var_dump(…

数据库查询求小于_SQL学习笔记(二)简单查询

本篇主要学习如何通过简单查询获取想要的数据。从零学会SQL&#xff1a;简单查询​www.zhihu.com基本的查询语句从数据库中查找数据时要使用select子句&#xff0c;select子句是sql中使用最多、最基本的子句。子句是sql语句的组成要素&#xff0c;是以某一个关键字作为开始的语…

隐私计算 2.1秘密共享--问题模型及定义

1 秘密共享问题模型 1.1 富翁和三个儿子的故事 问题&#xff1a; 富翁想在自己的三个儿子中找一个最聪明的来继承自己的遗产&#xff0c;在保护好财富的同时&#xff0c;让其他两个人也参与进来&#xff0c;使得兄弟间和睦相处&#xff0c;家庭和谐。 大儿子的方案&#xff…

如何命令行结束react程序_想要成为前端Star 吗?一首歌时间将React / Vue 应用Docker 化...

前言 以前一直有疑问困扰着我&#xff1a;人人都在吹的Docker容器化&#xff0c;与前端有何关系&#xff1f;然而在近两年的编程生涯&#xff0c;在每一次产品迭代中&#xff0c;渐渐体会到了容器化其魅力所在。应用部署从刀耕火种&#xff0c;到DevOps崛起&#xff0c;原来不止…

什么是spark的惰性计算?有什么优势?_spark——spark中常说RDD,究竟RDD是什么?

本文始发于个人公众号&#xff1a;TechFlow&#xff0c;原创不易&#xff0c;求个关注今天是spark专题第二篇文章&#xff0c;我们来看spark非常重要的一个概念——RDD。在上一讲当中我们在本地安装好了spark&#xff0c;虽然我们只有local一个集群&#xff0c;但是仍然不妨碍我…

前端websocket获取数据后需要存本地吗_是什么让我放弃了Restful API?了解清楚后我全面拥抱GraphQL!...

背景REST作为一种现代网络应用非常流行的软件架构风格&#xff0c;自从Roy Fielding博士在2000年他的博士论文中提出来到现在已经有了20年的历史。它的简单易用性&#xff0c;可扩展性&#xff0c;伸缩性受到广大Web开发者的喜爱。REST 的 API 配合JSON格式的数据交换&#xff…

子集和问题 算法_LeetCode刷题实战90:子集 II

算法的重要性&#xff0c;我就不多说了吧&#xff0c;想去大厂&#xff0c;就必须要经过基础知识和业务逻辑面试算法面试。所以&#xff0c;为了提高大家的算法能力&#xff0c;这个公众号后续每天带大家做一道算法题&#xff0c;题目就从LeetCode上面选 &#xff01;今天和大家…

隐私计算 2.5 Blakley秘密共享方案

1 简介 作者&#xff1a;Blakley&#xff1b;时间&#xff1a;1979年&#xff1b;理念&#xff1a;基于高斯消元法。 2 具体实现 I 秘密分割算法 II 秘密重构算法 3 实例 设秘密S(3,10,5)S (3, 10, 5)S(3,10,5)&#xff0c;n5n 5n5, t3t 3t3。 I 秘密分割 &#xff0…

conda如何升级pytorch_Google Cloud TPUs 支持 Pytorch 框架啦!

在2019年PyTorch开发者大会上&#xff0c;Facebook&#xff0c;Google和Salesforce Research联合宣布启动PyTorch-TPU项目。项目的目标是在保持PyTorch的灵活性的同时让社区尽可能容易地利用云TPU提供的高性能计算。团队创建了PyTorch/XLA这个repo&#xff0c;它可以让使PyTorc…

隐私计算 2.6 秘密共享的同态特性

1 秘密共享的同态性 秘密共享的同态性&#xff1a;秘密份额的组合等价于组合的秘密共享份额。 假设A、B两方分别有秘密SAS^ASA和SBS^BSB&#xff1b;他们的值被随机拆分为S1A,…,SnAS_1^A, \dots, S_n^AS1A​,…,SnA​和S1B,…,SnBS_1^B, \dots, S_n^BS1B​,…,SnB​&#xff…

二阶龙格库塔公式推导_带你走进最美数学公式

同学们&#xff0c;我们先来跟老师欣赏一下数学中最优美的式子吧&#xff1f;是什么魔力让以上几个似乎毫不相干的数学中最特殊的数字能如此优美的写在同一个式子呢&#xff1f;是欧拉&#xff0c;是数学。0和1——老师就不用介绍啦&#xff0c;e是自然常数(natural constant)&…

隐私计算 2.9 秘密共享应用于横向联邦学习

1 简介 1.1 横向联邦学习 横向联邦学习也称为按样本划分的联邦学习&#xff0c;主要应用于各个参与方的数据集有相同的特征空间和不同的样本空间的场景&#xff0c;例如两个地区的城市商业银行可能在各自的地区拥有非常不同的客户群体&#xff0c;所以他们的客户交集非常小&a…

python缩进说法_【多选题】关于Python程序中与“缩进”有关的说法中,以下选项中错误的是()。...

问题&#xff1a;【多选题】关于Python程序中与“缩进”有关的说法中&#xff0c;以下选项中错误的是&#xff08;&#xff09;。更多相关问题 因方某将赵某打伤&#xff0c;方某住所地的市劳动教养委员会对方某作出劳动教养2年的决定&#xff0c;并将方某送交劳动 根据行政诉讼…

智能测井解释

1 智能测井解释的需求分析 1、岩性识别 2、储层划分 3、参数计算 4、流体判别 5、井数据批量处理 岩性识别&#xff1a;分类任务 曲线预测、曲线补齐&#xff1a;回归任务 2 岩性识别 2.1 岩性识别主要方法简介 目前岩性识别的方法主要有重磁、测井、地震、遥感、电 磁、地…