当前位置:网站首页>IO 复用
IO 复用
2022-08-03 05:23:00 【纸鸢805】
1. 端口复用设置
作用 : 解决address already is use 报错 的问题 ( 端口被占用, 可能没被释放 )
使用 : 放在socket 的 bind 前面;
int opt_val = 1;
//端口复用设置 socketfd1 网络连接标识符
setsockopt(socketfd1, SOL_SOCKET, SO_REUSEADDR, (const void*)&opt_val, sizeof(opt_val));
2. socket IO复用
复用一般有三种技术
1. select
不记录发出 I/O 者的描述符, 因此只能无差别轮询所有流,找出能读出数据,或者写入数据的流,采用的是数组存储;
2. poll
poll本质上和select没有区别,它将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态, 但是它没有最大连接数的限制,原因是它是基于链表来存储的。
3. epoll ( 下面介绍的函数就是epoll技术 )
应用场景
select的timeout参数精度为1nm,比poll和epoll的1ms精度更高,因此select适合实时性要求比较高的场景。select的可移植性非常的好。
poll没有最大描述符数量的限制,如果平台支持并且对实时性要求不高,应该使用poll而不是select
只需要运行在linux平台下,有大量的描述符需要同时轮询,并且这些连接最好时长连接。在监听少量的描述符的适合,体现不出epoll的优势。
2.1 关键函数
2.1.1 Epoll 的创建, 返回的是个数
int cpoll_size = epoll_create(int size);
2.1.2 Epoll 的操作 (增 删 改)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
参数 :
epfd :
epoll 结构体对象
op :
EPOLL_CTL_ADD 注册新的fd到epfd中
EPOLL_CTL_MOD 修改已注册的fd的监听事件
EPOLL_CTL_DEL 从epfd中删除一个fd
fd :
要监听的描述符
event :
表示要监听的事件
2.1.3 epoll_wait 函数等待事件的就绪,成功时返回就绪的事件数目
int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
例如:
epollwritefd = epoll_wait(epollfd, epolleventArr, 10, -1); //函数等待事件的就绪
参数:
调用失败时返回 -1,等待超时返回 0。
epfd 是epoll句柄
events 表示从内核得到的就绪事件集合 maxevents 告诉内核events的大小
timeout 表示等待的超时事件
2.2 socket IO复用 的使用 :
1. 定义struct epoll_event 结构体的对象, 与struct epoll_event 结构体数组。
struct epoll_event epollevent;
struct epoll_event epolleventArr[10];
int epollfd = 0; //epollevent 的数量
int epollwritefd = 0; //epolleventArr[10] 的数量
2. 设置 struct epoll_event 结构体对象监听的文件描述符 , 与监听事件( EPOLLIN )
epollevent.data.fd = socketfd1; //设置连接监听
epollevent.events = EPOLLIN; //设置监听的事件为有数据传输进来
3. 创建 epoll
epollfd = epoll_create(10);
if (epollfd == -1)
{
perror(" epoll_create error ! ");
}
4. epoll 添加
//添加 socketfd1 进 epollevent 中
epoll_ctl(epollfd, EPOLL_CTL_ADD, socketfd1, &epollevent);
5 . 函数等待事件就绪
epollwritefd = epoll_wait(epollfd, epolleventArr, 10, -1); //函数等待事件的就绪
if ( epollwritefd <= 0 )
{
perror(" epoll_wait error ! ");
}
6. 分为等待 客户端连接 与 客户端数据传递
循环 for (int i = 0; i < epollwritefd ; i++) 完成以下两种操作
// 客户端连接
if (epolleventArr[i].data.fd == socketfd1)
{
cout << epollfd << "服务器端正在等待客户端访问:" << endl;
//等待客户端访问, 阻塞函数
kehuduanfd = accept(socketfd1, NULL, NULL);
if (kehuduanfd == -1)
{
perror(" accept error ! ");
}
else
{
cout << "客户端 " << kehuduanfd << "访问服务器成功!" << endl;
epollevent.data.fd = kehuduanfd;
epollevent.events = EPOLLIN;
epoll_ctl(epollfd, EPOLL_CTL_ADD, kehuduanfd, &epollevent);
}
}
// 客户端传输数据到服务器
if(epolleventArr[i].events & EPOLLIN)
{
cout << " 有数据传输不是客户端登录 " << endl;
bzero(&stu1, sizeof(stu1));
res = read(epolleventArr[i].data.fd, &stu1, sizeof(STU));
if ( res > 0 )
{
cout << " res = " << res << endl;
cout << "stu1.stuId = " << stu1.stuId << endl;
cout << "stu1.stuName = " << stu1.stuName << endl;
cout << "stu1.miaoshu = " << stu1.miaoshu << endl;
bzero(&stu1, sizeof(STU));
}
else if ( res <= 0 ) // 客户端下线 (读到的数据为 0 就是客户端有问题应该是下线了)
{
cout << "客户端 " << kehuduanfd << "关闭" << endl;
epollevent.data.fd = kehuduanfd;
epollevent.events = EPOLLIN;
epoll_ctl(epollfd, EPOLL_CTL_DEL, epolleventArr[i].data.fd, &epollevent);
close(epolleventArr[i].data.fd);
}
}
边栏推荐
- 嵌入式实验二注意点
- Try setting CHROME_EXECUTABLE to a Chrome executable
- MySql 怎么查出符合条件的最新的数据行?
- 令人愉快的 Nuxt3 教程 (一): 应用的创建与配置
- TypeError: Cannot read property ‘xxxx‘ of undefined的解决方法
- Kettle 从资源库中载入新的转换出错(Invalid byte 1 of 1-byte UTF-8 sequence)
- 动态规划笔记
- Apache2-XXE漏洞渗透
- 中国食品微生物检测行业深度监测及投资战略规划建议报告2022~2028年
- Mysql 存储过程详解(procedure)
猜你喜欢
Sqli-labs-master靶场1-23关通关详细教程(基础篇)
Browser multi-threaded off-screen rendering, compression and packaging scheme
Let small program development into ` tailwind jit ` era
嵌入式实验二
MySQL 索引检索原理和B+Tree数据结构详解
Sentinel初次使用Demo测试
pta a.1003 的收获
MySQL 唯一索引 UNIQUE KEY 会导致死锁?
pta a.1030的dijkstra+DFS方法
Apache2-XXE vulnerability penetration
随机推荐
解析各种文本的年月日
TypeError: Cannot read property ‘xxxx‘ of undefined的解决方法
MySQL 慢查询
动漫:海贼王女
中国生活垃圾处理行业十四五规划与投融资模式分析报告2022~2028年
MySQL 优化建议详解
中国生产力促进中心”十四五”规划与发展规模分析报告2022~2028年
陆运信息系统——班列项目总结(一)
Playing with Markdown(2) - Extraction and Manipulation of Abstract Syntax Trees
对页码的使用总结
Ansible installation and deployment detailed process, basic operation of configuration inventory
中国聚氯乙烯(PVC)土工膜发展动态及投资前景预测报告2022~2028年
中国水产养殖行业市场投资分析及未来风险预测报告2022~2028年
Kotlin 中的泛型介绍
自定义封装组件-国际化-下拉搜索
Try setting CHROME_EXECUTABLE to a Chrome executable
MySQL 安装报错的解决方法
关于如何向FastAPI的依赖函数添加参数
Oracle 密码策略详解
东南亚跨境电商