半关闭、端口复用与IO多路复用

文章目录

    • 半关闭
    • 端口复用
    • IO多路复用(IO多路转接)
      • 模型
      • 解决措施
    • sellect
      • 缺点
    • poll
      • 应用
      • 缺点
    • epoll
      • 应用
      • 工作模式

半关闭

使用close(fd);所对应的文件描述符写和读都关闭了。
半关闭、端口复用与IO多路复用_第1张图片
半关闭、端口复用与IO多路复用_第2张图片

端口复用

半关闭、端口复用与IO多路复用_第3张图片
在这里插入图片描述
在这里插入图片描述
可以解决绑定失败的问题。

IO多路复用(IO多路转接)

半关闭、端口复用与IO多路复用_第4张图片
socket通信
io多路复用就是操作缓冲区
IO多路复用 是的程序能够同时监听多个文件描述符,能够提高程序的性能。
Linux下实现IO多路复用的系统调用主要有select、poll和epoll。

半关闭、端口复用与IO多路复用_第5张图片

模型

半关闭、端口复用与IO多路复用_第6张图片
半关闭、端口复用与IO多路复用_第7张图片
半关闭、端口复用与IO多路复用_第8张图片
每次循环遍历一遍,浪费资源。

解决措施

半关闭、端口复用与IO多路复用_第9张图片
遍历标志位,检查
半关闭、端口复用与IO多路复用_第10张图片

sellect

半关闭、端口复用与IO多路复用_第11张图片
半关闭、端口复用与IO多路复用_第12张图片
半关闭、端口复用与IO多路复用_第13张图片

fd_set:为1024bit的标志位寄存器,是一个传入传出参数,将需要检测的文件描述符位置1传入,内核负责判断需要检测的文件描述符是否有IO操作,若有标志位依然为1,若没有则标志位置0,检测完成传出。
readfds:检测读缓冲区有数据了,可以读了,置1
writefds:检测写缓冲区还有空余空间可以写,置1
timeout:如果为NULL,表示永久阻塞,直到检测到了文件描述符变化;如果都=0, 不阻塞;如果时间>0,阻塞对应的时间。
返回值:
-1表示调用失败
>0:表示有几个文件描述符发生了变化

半关闭、端口复用与IO多路复用_第14张图片

半关闭、端口复用与IO多路复用_第15张图片

socket监听之后,进行文件描述符集合设置;
设置完成进行select,有文件描述符发生变化会有返回值,否则阻塞
判断哪个文件描述符发生了变换,进行相应的处理;
socket文件描述符发生变化,获取客户端连接文件描述符,并添加到集合
客户端连接文件描述符发生变化,对数据进行处理。

半关闭、端口复用与IO多路复用_第16张图片
半关闭、端口复用与IO多路复用_第17张图片
判断socket文件描述符,是否有新连接:
半关闭、端口复用与IO多路复用_第18张图片
判断其他描述符,是否有数据来:
半关闭、端口复用与IO多路复用_第19张图片
注意 : 上面的代码的问题是,设置rdset后传入传出后被修改了,下次传入不是想要的了,可以定义一个传入传出的集合tmp,一个设置的集合rdset,每次需要select时将设置集合赋值给tmp,进行操作。

缺点

半关闭、端口复用与IO多路复用_第20张图片

poll

半关闭、端口复用与IO多路复用_第21张图片
半关闭、端口复用与IO多路复用_第22张图片
timeout:阻塞时间,单位为ms。
返回值:
-1:失败
>0(n):n个检测到集合中有n个文件描述符发生变化。
事件设置举例(通过|实现多个事件值):
半关闭、端口复用与IO多路复用_第23张图片

应用

半关闭、端口复用与IO多路复用_第24张图片
半关闭、端口复用与IO多路复用_第25张图片

判断返回值,判断事件:
半关闭、端口复用与IO多路复用_第26张图片
增加文件描述符:
从最开始向后遍历,找到最前面没有使用的文件描述符。
半关闭、端口复用与IO多路复用_第27张图片
遍历搜索是哪个文件描述符发生事件,要从lfd开始,到最大文件描述符,索引下标则从0开始,到最大有文件描述符的下标。

缺点

半关闭、端口复用与IO多路复用_第28张图片
改善了3.4条缺点,但其他依然存在。

epoll

创建,在内核就存在一个eventpoll实例,并返回内核缓冲区中的文件描述符
操作
检测
半关闭、端口复用与IO多路复用_第29张图片
半关闭、端口复用与IO多路复用_第30张图片
返回值:
-1:调用失败
>0:文件描述符,操作epoll的实例
半关闭、端口复用与IO多路复用_第31张图片
三个事件分别是读、写、错误。
半关闭、端口复用与IO多路复用_第32张图片
半关闭、端口复用与IO多路复用_第33张图片

应用

半关闭、端口复用与IO多路复用_第34张图片
半关闭、端口复用与IO多路复用_第35张图片
半关闭、端口复用与IO多路复用_第36张图片
半关闭、端口复用与IO多路复用_第37张图片
半关闭、端口复用与IO多路复用_第38张图片
半关闭、端口复用与IO多路复用_第39张图片
注意 :这个地方对epoll监听的事件如果有多种,就要对事件进行判断,防止出现错误判断应用;对其判断就是通过epevs[i].enents & EPOLL…进行判断(返回值与事件与)。

工作模式

LT模式和ET模式
半关闭、端口复用与IO多路复用_第40张图片
上边缺省的工作方式就是默认工作方式。
读一次也算操作了,即使缓冲区里有数据也不重复通知,直到有新数据进来才会再进行新的通知。

两者区别:LT模式:
半关闭、端口复用与IO多路复用_第41张图片
ET模式:
半关闭、端口复用与IO多路复用_第42张图片
设置ET模式(在设置事件时或上EPOLLET):

半关闭、端口复用与IO多路复用_第43张图片
半关闭、端口复用与IO多路复用_第44张图片
再ET模式下数据读取可采用循环读取方式:
可以通过循环读取数据,直到读取结束,
read阻塞控制是由于文件描述符属性控制,所以可以通过设置文件描述符属性,改变为非阻塞:
需要头文件:
#include
#include

//设置cfd属性非阻塞
int flag = fcntl(cfd, F_GETFL);
flag |= O_NONBLOCK;
fcntl(cfd, F_SETFL, flag);

半关闭、端口复用与IO多路复用_第45张图片
非阻塞情况,没有数据read会返回-1,错误号为EAGAIN,可通过判断处理
半关闭、端口复用与IO多路复用_第46张图片

打印到终端的方式
write(STDOUT_FILENO, buf, len);
printf(“%s\n”, buf);

你可能感兴趣的:(Linux,数据库,服务器)