Android C++系列:Linux Socket编程(四)多路IO转接服务器

简介: select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开 的文件描述符个数并不能改变select监听文件个数

image.png


1. select


1.select能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开 的文件描述符个数并不能改变select监听文件个数


2.解决1024以下客户端时使用select是很合适的,但如果链接客户端过多,select采用 的是轮询模型,会大大降低服务器响应效率,不应在select上投入更多精力


#include <sys/select.h>
/* According to earlier standards */ 
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
void FD_CLR(int fd, fd_set *set);
把文件描述符集合里fd清0


  • nfds: 监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件描述符的状态
  • readfds:监控有读数据到达文件描述符集合,传入传出参数
  • writefds:监控写数据到达文件描述符集合,传入传出参数
  • exceptfds:监控异常发生达文件描述符集合,如带外数据到达异常,传入传出参数
  • timeout:定时阻塞监控时间,3种情况


  1. NULL,永远等下去
  2. 设置timeval,等待固定时间
  3. 设置timeval里时间均为0,检查描述字后立即返回,轮询


struct timeval {
  long tv_sec;/* seconds */
  long tv_usec;/*microseconds */
};
int FD_ISSET(int fd, fd_set *set); 
void FD_SET(int fd, fd_set *set); 
void FD_ZERO(fd_set *set);
测试文件描述符集合里fd是否置1 把文件描述符集合里fd位置1 把文件描述符集合里所有位清0


2. poll


#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd { 
  int fd; /* 文件描述符 */
  short events; /* 监控的事件 */
  short revents;/* 监控事件中满足条件返回的事件 */
};


  • POLLIN普通或带外优先数据可读,即POLLRDNORM | POLLRDBAND
  • POLLRDNORM-数据可读
  • POLLRDBAND-优先级带数据可读
  • POLLPRI 高优先级可读数据
  • POLLOUT普通或带外数据可写
  • POLLWRNORM-数据可写
  • POLLWRBAND-优先级带数据可写
  • POLLERR 发生错误
  • POLLHUP 发生挂起 POLLNVAL 描述字不是一个打开的文件


nfds 监控数组中有多少文件描述符需要被监控 timeout 毫秒级等待


  • -1:阻塞等,#define INFTIM -1 Linux中没有定义此宏


  • 0:立即返回,不阻塞进程


  • 0:等待指定毫秒数,如当前系统时间精度不够毫秒,向上取值


如果不再监控某个文件描述符时,可以把pollfd中,fd设置为-1,poll不再监控此 pollfd,下次返回时,把revents设置为0。


ppoll GNU定义了ppoll(非POSIX标准),可以支持设置信号屏蔽字,可参考poll模型自 行实现C/S


3. epoll


epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并 发连接中只有少量活跃的情况下的系统CPU利用率,因为它会复用文件描述符集合来传递结 果而不用迫使开发者每次等待事件之前都必须重新准备要被侦听的文件描述符集合,另一点 原因就是获取事件的时候,它无须遍历整个被侦听的描述符集,只要遍历那些被内核IO事件 异步唤醒而加入Ready队列的描述符集合就行了。


目前epell是linux大规模并发网络程序中的热门首选模型。


epoll除了提供select/poll那种IO事件的电平触发(Level Triggered)外,还提 供了边沿触发(Edge Triggered),这就使得用户空间程序有可能缓存IO状态,减少 epoll_wait/epoll_pwait的调用,提高应用程序效率。


一个进程打开大数目的socket描述符cat /proc/sys/fs/file-max


4. 总结


本文介绍了Linux多路复用的三种技术:select、poll、epoll。

目录
相关文章
|
网络协议 安全 Linux
Linux C/C++之IO多路复用(select)
这篇文章主要介绍了TCP的三次握手和四次挥手过程,TCP与UDP的区别,以及如何使用select函数实现IO多路复用,包括服务器监听多个客户端连接和简单聊天室场景的应用示例。
430 0
|
存储 Linux C语言
Linux C/C++之IO多路复用(aio)
这篇文章介绍了Linux中IO多路复用技术epoll和异步IO技术aio的区别、执行过程、编程模型以及具体的编程实现方式。
783 1
Linux C/C++之IO多路复用(aio)
|
9月前
|
Linux C语言 网络架构
Linux的基础IO内容补充-FILE
而当我们将运行结果重定向到log.txt文件时,数据的刷新策略就变为了全缓冲,此时我们使用printf和fwrite函数打印的数据都打印到了C语言自带的缓冲区当中,之后当我们使用fork函数创建子进程时,由于进程间具有独立性,而之后当父进程或是子进程对要刷新缓冲区内容时,本质就是对父子进程共享的数据进行了修改,此时就需要对数据进行写时拷贝,至此缓冲区当中的数据就变成了两份,一份父进程的,一份子进程的,所以重定向到log.txt文件当中printf和fwrite函数打印的数据就有两份。此时我们就可以知道,
213 0
|
9月前
|
存储 Linux Shell
Linux的基础IO
那么,这里我们温习一下操作系统的概念我们在Linux平台下运行C代码时,C库函数就是对Linux系统调用接口进行的封装,在Windows平台下运行C代码时,C库函数就是对Windows系统调用接口进行的封装,这样做使得语言有了跨平台性,也方便进行二次开发。这就是因为在根本上操作系统确实像银行一样,并不完全信任用户程序,因为直接开放底层资源(如内存、磁盘、硬件访问权限)给用户程序会带来巨大的风险。所以就向银行一样他的服务是由工作人员隔着一层玻璃,然后对顾客进行服务的。
131 0
|
存储 网络协议 Linux
【Linux】进程IO|系统调用|open|write|文件描述符fd|封装|理解一切皆文件
本文详细介绍了Linux中的进程IO与系统调用,包括 `open`、`write`、`read`和 `close`函数及其用法,解释了文件描述符(fd)的概念,并深入探讨了Linux中的“一切皆文件”思想。这种设计极大地简化了系统编程,使得处理不同类型的IO设备变得更加一致和简单。通过本文的学习,您应该能够更好地理解和应用Linux中的进程IO操作,提高系统编程的效率和能力。
577 34
|
网络协议 开发者 Python
Socket如何实现客户端和服务器间的通信
通过上述示例,展示了如何使用Python的Socket模块实现基本的客户端和服务器间的通信。Socket提供了一种简单且强大的方式来建立和管理网络连接,适用于各种网络编程应用。理解和掌握Socket编程,可以帮助开发者构建高效、稳定的网络应用程序。
621 10
|
机器学习/深度学习 API Python
Python 高级编程与实战:深入理解网络编程与异步IO
在前几篇文章中,我们探讨了 Python 的基础语法、面向对象编程、函数式编程、元编程、性能优化、调试技巧、数据科学、机器学习、Web 开发和 API 设计。本文将深入探讨 Python 在网络编程和异步IO中的应用,并通过实战项目帮助你掌握这些技术。
|
Linux API C语言
Linux基础IO
Linux基础IO操作是系统管理和开发的基本技能。通过掌握文件描述符、重定向与管道、性能分析工具、文件系统操作以及网络IO命令等内容,可以更高效地进行系统操作和脚本编写。希望本文提供的知识和示例能帮助读者更深入地理解和运用Linux IO操作。
287 14
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
923 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输