1.网络服务器
(1)单循环服务器通常指一种非常简单的网络服务器,它使用单个线程不断地接收和处理来自客户端的请求。单循环服务器适合处理少量的并发连接,但随着连接数的增加,它会导致性能问题,因为单个线程无法高效地处理大量的并发连接。
(2)并发网络服务器使用多个线程或进程来处理多个客户端连接,以提高服务器的性能和并发能力。
2.并发网络服务器可分为多进程,多线程以及IO多路复用
多进程并发服务器:
优点:每个进程都拥有独立的内存空间和系统资源,进程间不会互相干扰,提高了系统的稳定性,在一个进程崩溃时,其他进程不会受到影响。
缺点:每个进程都需要消耗一定的系统资源,包括内存和CPU时间,进程间的通信和切换比线程间的通信和切换更加耗时,效率较低。
多线程并发服务器:
优点:线程间共享同一进程的内存空间,使得多线程在并发处理上具有更高的效率,相比于多进程,多线程能够更节省资源,特别是内存资源。
缺点:
多个线程可能会同时访问共享资源,可能会导致资源侵占,还有可能导致死锁。
IO多路复用并发服务器:
IO多路复用是多个IO对一个进程多次访问
(1)select:
1. 创建文件描述符集合 fd_set
2. 添加文件描述符到集合中 void FD_SET(int fd, fd_set *set);
3. 通知内核开始监测 select
4. 根据返回的结果做对应的操作(对io读、写操作)
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
功能:监测多路IO
参数:
nfds : 关注的文件描述符中的最大值+1
readfds:关注的读事件的文件描述符集合
writefds:关注的写事件的文件描述符结合
exceptfds:其他 异常
timeout : 超时时间,如果不设置:NULL
返回值:
成功:返回到达事件的个数
失败:-1
设置了超时时间:超时时间到达但没有事件,返回0
宏:
void FD_CLR(int fd, fd_set *set);
int FD_ISSET(int fd, fd_set *set);
void FD_SET(int fd, fd_set *set);
void FD_ZERO(fd_set *set);
优缺点:
1.select监听文件描述符最大个数为1024 (数组) O(n)
2.select监听的文件描述符集合在用户层,需要应用层和内核层互相传递数据
3.select需要循环遍历一次才能找到产生的事件
4.select只能工作在水平触发模式(低速模式)无法工作在边沿触发模式(高速模式)
(2)epoll:监控多路IO
1. 创建文件描述符集合 int epoll_create(int size);
2. 添加文件描述符到集合中 epoll_ctl()
3. 通知内核开始监测 epoll_wait()
4. 根据返回的结果做对应的操作(对io读、写操作)
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:
参数:
epfd:文件描述符集合句柄
op:
EPOLL_CTL_ADD: 向集合中添加文件描述符
EPOLL_CTL_MOD: 修改集合
EPOLL_CTL_DEL :删除文件描述符
fd :操作的文件描述符
event :文件描述符所对应的事件
共用体:typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;
struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
event : EPOLLIN : 读操作
EPOLLOUT : 写事件
int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);
功能:监测IO事件
参数:
epfd : 文件描述符集合句柄
events : 保存到达事件的结合的首地址
maxevents : 监测时事件的个数
timeout:超时时间
-1 :不设置超时时间
返回值:
成功:返回到达事件的个数
失败:-1
设置超时:超时时间到达返回0
优点:
1.epoll创建内核事件表,不受到文件描述符上限限制 (红黑树) O(logn)
2.epoll监听的事件表在内核中,直接在内核中监测事件效率高
3.epoll会直接获得产生事件的文件描述符的信息,而不需要遍历检测
4.epoll既能工作在水平触发模式,也能工作在边沿触发模式
3.常见的IO模型:
(1) 阻塞IO:
应用程序发起一个IO请求后,会一直阻塞等待操作完成,直到数据准备好或者超时才返回结果。这种模型在IO操作期间会阻塞当前线程,无法执行其他任务,适用于连接数较少的场景。
(2)非阻塞IO:
应用程序发起一个IO请求后会立即返回,无需等待操作完成。应用程序需要不断轮询或者使用事件通知来检查操作是否完成。这种模型适用于需要处理多个连接或者连接数较多的场景,但效率不高。
(3)信号驱动IO:
应用程序通过向内核注册信号处理函数来处理IO事件。当IO操作完成时,内核会发送一个信号通知应用程序,然后由应用程序在信号处理函数中处理该事件。这种模型相比阻塞IO和非阻塞IO更为灵活,但信号队列在Linux中有限制,可能导致无法读取数据。
(4)IO多路复用:
IO多路复用模型使用操作系统提供的select、poll或epoll等多路复用机制,允许应用程序同时监视多个IO事件。应用程序可以将多个IO请求注册到一个多路复用器上,然后通过轮询或者阻塞等待多路复用器通知事件的发生。这种模型适用于需要同时处理多个连接的场景,提高了系统的并发性能。