当前位置: 首页 > news >正文

关于linux网络编程——3

一、单循环服务器
特点:
1.可以处理多个客户端 (不能同时)
2.效率不高

//单循环服务器:
socket
bind
listen
while (1)
{connfd =  accept();//通信 
}特点:简单 可以处理多客户端 不能同时 

二、并发服务器    --- 同时可以处理多个客户端

1、设置一个选项(开启一个功能) ---让地址重用

int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
功能:设置socket的属性参数:	 @sockfd   --- 要设置的socket @level    --- 设置socket层次 //socket本身 tcp ip @optname  --- 选项名字 @optval   --- 选项值 @optlen   --- 长度 设置一个选项(开启一个功能) ---让地址重用 地址重用:

//并发服务器 --- 同时处理多个客户端 
socket
bind
listen
while (1)
{
connfd =  accept();
//通信 
//进程
// ---专门创建一个子进程 --- 负责通信过程    
//线程
// ---专门创建一个线程 --- 负责通信过程   
}

//并发服务器 --- 同时处理多个客户端 
socket
bind
listen
while (1)
{connfd =  accept();//通信 //进程// ---专门创建一个子进程 --- 负责通信过程    //线程// ---专门创建一个线程 --- 负责通信过程   
}

将两个任务:
1.负责完成连接操作 
accept   
2.负责通信的 

多进程 和 多线程

并发服务器 ---多进程方式的效率 肯定 低于 多线程

三、更高效的方式:多路IO复用

多路IO 
I   --- input
O   --- output
复用 
一个进程 
一个线程 可以处理多路IO 
//这多路IO 复用了这个一个进程 或是线程

比较:

//并发服务器 --- 同时处理多个客户端 
socket
bind
listen
while (1)
{
connfd =  accept();
//通信 
//进程
// ---专门创建一个子进程 --- 负责通信过程    
//线程
// ---专门创建一个线程 --- 负责通信过程   
}


//一路io
accept
//另一路io
负责通信

多路IO 
把负责通信的那个进程 或 线程 
用来处理多个客户端的通信

/多进程或多线程的并发服务器

一个客户端 ----> 一个进程 或 线程 


//IO多路复用 
N个客户端 -----> 一个进程 或 线程

提高并发的能力

        socket  
|
bind
|
listen
|
accept
|
do_client1 do_client2  do_client3


socket  
|
bind
|
listen
|
accept
|
do_client1   do_client2  do_client3
|   |   |
cli1 cli2 cli3 cli4 cli5 cli6 cli7 cli8 cli9  

四、多路IO复用功能的相关函数

select
poll
epoll

五、IO处理的模型

阻塞IO模型:i -- 读 scanfgetcharfgetsreadrecvo -- 写写有阻塞    //管道 读端存在 写管道

阻塞IO模型:

以读为例:
读操作--->内核中读取数据--->如果没有数据,一直等到,直到有数据--->之后将数据带回到用户空间        
非阻塞IO模型:
以读为例:
读操作--->内核中读取数据--->如果没有数据,不等,直接返回用户空间

阻塞 与 非阻塞 是操作对象的特性 

5.1设置非阻塞的函数 fcntl

//设置非阻塞 
fcntl
#include <unistd.h>
#include <fcntl.h>int fcntl(int fd, int cmd, ... /* arg */ );
功能:维护文件描述符
参数:@fd  --- 要操作的fd@cmd --- 要做的一些操作 //command@... --- 可变参数 
返回值 取决于所做的操作 
int printf(const char *format, ...);printf("hello world!\n");
printf("a = %d\n",a);
printf("a = %d b = %c\n",a,b);设置非阻塞
int flags;
flags = fcntl(fd,F_GETFL,0); //读 
flags = flags | O_NONBLOCK;  //修改 
fcntl(fd,F_SETFL,flags);     //写 点对点聊天client  <----------> serverfgetswrite/send -----> recv/read printf fgetsread<------writeprintf

5.2信号驱动IO:

信号驱动IO//signal
1.fcntl  --- 设置 信号接受者 flags = fcntl(fd,F_GETFL); //获得当前标志 fcntl(fd,F_SETFL,flags|O_ASYNC); O_ASYNC //开启异步操作 //同步 //A->B//异步 //A//B
2.将该程序 和 SIGIO信号关联起来 fcntl(fd,F_SETOWN,pid);//OWNER 
3.设置信号处理函数 signal(SIGIO)如果 程序要处理多路IO   缺点:处理的数量有限 

IO多路复用方式 
//可以处理多路IO 
//不需要 阻塞
//不需要 轮询 

因此

六、IO多路复用方式:

6.1slect函数;

select 
0  --- 读
1  --- 写
2  --- 出错int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);功能:实现IO多路复用 @nfds      //是关心的文件描述符中最大的那个文件描述符 + 1  
@readfds   //代表 要关心 的 读操作的文件描述符的集合 
@writefds  //代表 要关心 的 写操作的文件描述符的集合
@exceptfds //代表 要关心 的 异常的文件描述符的集合
@timeout   //超时 --- 设置一个超时时间 //NULL 表示select是一个阻塞调用 //设置时间 //         0 --- 非阻塞 //    n (>0) --- 阻塞n这么长时间 //注意: 这个值 每次 自动在往下减少 --直到减少到0struct timevalstruct timeval {long    tv_sec;         /* seconds */long    tv_usec;        /* microseconds */};struct timeval t = {0,0};返回值:成功 返回就绪的文件描述符的数量 失败 -1 

6.2select函数使用的整体思路:

//select使用时的整体思路:
1.建立一张表  监控fd_set readfds; //一张表 			  FD_ZERO(&readfds); //清空这张表			  
2.将要监控的文件描述符 添加表中 FD_SET(0,&readfds);FD_SET(fd,&readfds);3. nfds = fd + 1; 
select(nfs,&readfds,NULL,NULL,NULL)void FD_CLR(int fd, fd_set *set); //将fd从set集合中清除 
int  FD_ISSET(int fd, fd_set *set);//判断fd是否在set中 
void FD_SET(int fd, fd_set *set);//将fd添加到set集合中
void FD_ZERO(fd_set *set);//将set集合清空 

6.3使用:

多路IO复用的服务器: //实现并发 --- 可以同时处理多个客户端listenfd = socket
bind
listen
//connfd = accept
//1.准备表fd_set readfds;FD_ZERO(&readfds);
//2.添加要监控的文件描述符 FD_SET(listenfd,&reafds);
//3.准备参数 maxfds = listenfd + 1;fd_set backfds; 
while (1)
{   backfds = readfds;int ret = select(maxfds,&backfds,NULL,NULL,NULL);if (ret > 0){int i = 0;for (i = 0; i < maxfds;++i){if (FD_ISSET(i,&backfds)){if (i == listenfd) //连接 {connfd = accept();//connfd 要被添加到 监控表FD_SET(connfd,&readfds);if (connfd + 1 > maxfds)maxfds = connfd + 1;}else //负责与客户端通信 {//	i = ?//fd 此时就绪 printf("buf = %s\n",buf);if (strncmp(buf,"quit",4) == 0){FD_CLR(i,&readfds); //清除对应的客户端的fdclose(i);	}}}}}
}//优化
int i = maxfds;
for (i = maxfds-1; i >= 0; --i)
{if (FD_ISSET(i,&readfds)){maxfds = i + 1;}
}

不足:   

 1. 最大监听数受限:`FD_SETSIZE` 默认 1024(Linux)
2. 每次调用需重置 fd_set:内核会修改集合,必须每次重新 `FD_SET`
3. 用户态与内核态拷贝开销大
4. 返回后仍需遍历所有 fd 才能知道哪个就绪
5. 效率随 fd 数量增长下降明显


文章转载自:

http://m0TBZ6WK.syynx.cn
http://SQgqSAdr.syynx.cn
http://3uQILw0H.syynx.cn
http://oqkcWOTm.syynx.cn
http://wBgADief.syynx.cn
http://6tstdqPo.syynx.cn
http://crXEWFzF.syynx.cn
http://CMakRA2F.syynx.cn
http://lnnO6fl0.syynx.cn
http://7rgZCMPc.syynx.cn
http://LGVbkbIg.syynx.cn
http://SUbGZd2Z.syynx.cn
http://UROh6Ing.syynx.cn
http://0yLM8Lzr.syynx.cn
http://RNULP4iK.syynx.cn
http://LEyZ5GfI.syynx.cn
http://rVKRQxF5.syynx.cn
http://BQO6o3iL.syynx.cn
http://absTQngX.syynx.cn
http://cf8y9iax.syynx.cn
http://6BnMruhY.syynx.cn
http://rqQGjRe1.syynx.cn
http://ia7kyRVs.syynx.cn
http://ZRXXFOJo.syynx.cn
http://hUNUq9bZ.syynx.cn
http://3Y2wD5gU.syynx.cn
http://QumRbrbZ.syynx.cn
http://gz2yXhPl.syynx.cn
http://Casds84L.syynx.cn
http://10gQrqUt.syynx.cn
http://www.dtcms.com/a/365149.html

相关文章:

  • 扫地日记:有鹿巡扫机器人在景区被人类“调戏”的365天
  • ansible总结2
  • GIS大学课程表都长啥样?几个地信专业的大学一周课程表
  • 如何评价2025年数学建模国赛?
  • (二)文件管理-基础命令-pwd命令的使用
  • 高并发数据写入场景下 MySQL 的性能瓶颈与替代方案
  • “我店”积分模式的可持续性拷问:短剧能否撑起长期消泡沫需求?
  • 蓝桥杯算法之基础知识(6)
  • Python函数和方法类型注释
  • k8s使用StatefulSet(有状态)部署单节点 MySQL方案(使用本地存储)
  • 【Python】 Python 项目初始化脚本
  • JavaWeb03
  • EagleTrader观察|你的固定心态,可能正在悄悄让你交易破产
  • 【踩坑记录】Unity 项目中 PlasticSCM 掩蔽列表引发的 文件缺失问题排查与解决
  • 3种通过USB从电脑传输文件到iPad的方法
  • Python_occ 学习记录 | 细观建模(1)
  • Ubuntu查看开机以来修改的文件
  • 论文介绍“DUSt3R”:让 3D 视觉从“繁琐”走向“直观”
  • 语音合成之二十六 TTS情感控制技术开源数据集
  • PHP如何解决使用国密SM4解密Base64数据错误问题?(基于lpilp/guomi)
  • [论文阅读] 人工智能 + 软件工程 | ReCode:解决LLM代码修复“贵又慢”!细粒度检索+真实基准让修复准确率飙升
  • 一键 i18n 国际化神库!适配 Vue、React!
  • CMake构建学习笔记24-使用通用脚本构建PROJ和GEOS
  • Web端最强中继器表格元件库来了!55页高保真交互案例,Axure 9/10/11通用
  • Java学习笔记-零基础学MySQL(四)
  • 三阶Bezier曲线,已知曲线上一点到曲线起点的距离为L,计算这个点的参数u的方法
  • 【C++】C++入门—(中)
  • MySQL 开发避坑:DROP TABLE 前你必须知道的几件事
  • 【题解】洛谷P1776 宝物筛选 [单调队列优化多重背包]
  • 2.插值法