Linux网络编程5——多路IO转接服务器

学习视频链接
黑马程序员-Linux网络编程_哔哩哔哩
目录
一、多路 IO 服务器
【Linux网络编程5——多路IO转接服务器】1.1 分类
1. 原理图
二、 函数
2.1 传入、传出参数
2.2 函数和后续分析
2.3 配套函数
2.4 代码
2.5 linux和通信
2.的优缺点
2.7添加一个自己定义数组提高效率
一、多路 IO 服务器 1.1 分类
模型
poll 模型
epoll 模型
1. 原理图
这里不是等待客户端连接,而是客户端想要连接需要需要通知,然后把信息交给主函数,主函数执行 (),然后由负责去写数据 。涉及到阻塞、非阻塞轮询、响应式——多路 IO 转接,上述例子是多路 IO 转接
二、 函数 2.1 传入、传出参数
程序启动起来后 0 1 2 这 3 个文件描述符就被占用了 。后面的文件描述符 3 被 lfd 占用,用于监听,后面的连接依次占用文件描述符 4、5、6 ...
客户端连接上后没有发送信息的话,就不需要读监听,想监听的话就把对应的文件描述符放入读集合 (r) 就可以了 。写和异常的监听放在另外两个集合里面
现阶段没有这两种需求,所有传入 NULL 就行了
2.2 函数和后续分析
1、函数
int (int nfds,*,*,*,*);
nfds: 监控的文件描述符集里最大文件描述符加 1,因为此参数会告诉内核检测前多少个文件描述符的状态
: 监控有读数据到达文件描述符集合,传入传出参数
: 监控写数据到达文件描述符集合,传入传出参数
: 监控异常发生达文件描述符集合,如带外数据到达异常,传入传出参数
: 定时阻塞监控时间,3种情况 。
(1) NULL,永远等下去
(2) 设置,等待固定时间 。
(3) 设置里时间均为 0,检查描述字后立即返回,轮询
2、分析
函数最后一个参数设置轮询的时间,在监听期间有发送信息的话,会放入到传出参数中,传出参数同样使用位图
一开始监听 3、5、6 文件描述符对应的读 (r),3 在监听的时候没有读 (r),所以传出中的位图没有 3 了
2.3 配套函数
void ( *set); —— 清空一个文件描述符集合
rset;
(&rset);
void (int fd,*set); —— 将待监听的文件描述符,添加到监听集合中
(3, &rset);
(5, &rset);
(6, &rset);
void (int fd, fd_ set *set); —— 将一个文件描述符从监听集合中移除

Linux网络编程5——多路IO转接服务器

文章插图
(4, &rset);
int (int fd,*set); —— 判断一个文件描述符是否在监听集合中
返回值: 在返回1;不在返回0
(4, &rset);
2.4 代码
进入 while 前,监听的位图就是上图这个,maxfd 对应的值是 3
#include #include #include #include #include #include #include #include #include #include #define SERV_PORT 6666void sys_err(const char* str) {perror(str);exit(1);}int main(void){int i, j, n, nready;int maxfd = 0;int listenfd, connfd;char buf[BUFSIZ];struct sockaddr_in clie_addr, serv_addr;socklen_t clie_addr_len;listenfd = socket(AF_INET, SOCK_STREAM, 0);// 创建一个socket, 得到lfdint opt = 1;setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); // 设置端口复用bzero(&serv_addr, sizeof(serv_addr));// 地址结构清零serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);// 指定本地任意IPserv_addr.sin_port = htons(SERV_PORT);// 指定端口号bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr));// 绑定listen(listenfd, 128);// 设置同一时刻链接服务器上限数fd_set rset, allset;// rset读事件文件描述符 allset用来暂存maxfd = listenfd;FD_ZERO(&allset);FD_SET(listenfd, &allset); // 构造select监控文件描述符集while (1) {rset = allset;// 每次循环时都要重新设置select监控信号集nready = select(maxfd + 1, &rset, NULL, NULL, NULL);if (nready