并发服务器、多路IO复用

目录

服务器模型:IO多路复用

常见的IO操作模型

[阻塞IO:scanf(); getchar(); fgets();](#阻塞IO:scanf(); getchar(); fgets();)

[非阻塞IO :](#非阻塞IO :)

信号驱动IO

[int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);](#int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);)

select使用流程

epoll

[① int epoll_create(int size);](#① int epoll_create(int size);)

epoll_ctl

epoll_wait


显卡

声卡

网卡:能让你上网的

URL的一般形式

<协议>://<主机 ip> : <端口>/

strstr --> char *strcasestr(const char *haystack, const char *needle);

功能:从中找字符串

参数:

返回值:返回找到的子字符串的起始位置

客户端:并发服务器------支持多个用户同时访问

循环服务器(迭代服务器)

while(1)

{

//连接

accept(); //问题1:阻塞操作------在等待队列中没有连接请求时会阻塞

while(1) //问题2:通信过程可能是一个耗时操作

{

//通信recv();send();}}

实现简单。可以处理多个客户端,但是只能是串行

并发服务器

while(1)

{connfd = accept();

fork() 或 pthread_create()

}

多进程:资源开销大,进程的退出要考虑僵尸态资源的回收

多线程:线程的创建和调度开销小,线程共享资源方便,线程之间竞争和同步问题

服务器模型:IO多路复用

核心目的 ------ 提高并发的程度

多路IO ------ 当前进程有多处输入输出的操作

复用 ------ 服复用的是当前进程或线程

应用:在一个进程中有多个线程要执行

系统开销小,也不用创建线程和进程,不用维护,减少系统的开销

常见的IO操作模型

阻塞IO:scanf(); getchar(); fgets();

  • 常见的主要是读取、写入、管道(64kb大小空间)
  • 当读取数据时,内核没有数据,读取操作会一直阻塞,直到内核获得数据
  • 特点:实现简单,效率不高

非阻塞IO :

特点:当去内核读取数据时,如果内核没有数据,他不阻塞等待,而是立即返回,所以非阻塞方式想要获得数据,需要配合轮询操作

while(1)

{

recvfrom(); //非阻塞一直要轮询到等读到数据

}//很耗CPU

信号驱动IO

  • 1 设置好对SIGIO的信号处理函数,等有数据来了,内核会给进程发信号,进程收到信号后,再去做读取操作,不需要一直等也不需要轮询
  • 使用流程:
  • 为内核发送的通知信号安装一个信号处理例程,默认情况下,这个通知信号为SIGIO
  • //signal 或 sigaction
  • signal(SIGIO,handler);
  • 2 设定文件描述符的属主,也就是当文件描述符上可执行IO时会接收到通知信的进程或进程组,通常我们让调用进程成为属主,设定属主可通过fcntl();的F_SETOWN操作来完成
  • //owner
  • fcntl();
  • 异步的效率高,但是只能处理一路IO
  • 3 设置标志:通过设定O_NONBLOCK标志使能非阻塞IO;通过打开O_ASYNC标志使能信号驱动IO;这可以一个操作,因为它们都需要用到fcntl()的F_SETFL操作

IO多路复用

int select(int nfds, fd_set *readfds, fd_set *writefds,

fd_set *exceptfds, struct timeval *timeout);

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);

select使用流程

  1. 准备监控文件描述符表:fd_set readfds;FD_ZERO(&readfds);
  2. 添加要监控的文件描述符:FD_SET(fd,&readfds);FD_SET(0,&readfds);
  3. 准备nfsd:nfds = n+1;
  4. 调用select函数:select(nfsd,&readfds,NULL,NULL,NULL);
cpp 复制代码
select 实现并发:
1.listenfd=socket
2.bind
3.listen

//1.准备表
    fd_set readfds;
	//清空
	FD_ZERO(&readfds);
//2.添加要监控的文件描述符到表中
	//listenfd
	FD_SET(listenfd,readfds);
//3.调用select函数进行监控
//1.nfds --> 最大的文件描述符+1
	int nfds = listenfd + 1; //注意: 是三个集合中最大的文件描述符加1
	int ret = 0;
	int i = 0;
	fd_set bakfds = readfds;
while (1)
{
    bakfds = readfds;
    ret = select(nfds,&bakfds,NULL,NULL,NULL); 
    
	if (ret > 0) 
	{ //表示有就绪的文件描述符
        //寻找具体是哪个文件描述符就绪
        for (i = 0; i < nfds; i++) 
		{
            if (FD_ISSET(i,&bakfds)) 
			{ //只能判断出 i 是否在bakfds中
               if (i == listenfd)  //意味着有客户端发起连接请求 
			   {
                    connfd = accpet();
                    //实现并发,添加对新连接的套接字的监控
                   
 				    //1. 添加到要监控的表中,进行监控
                    FD_SET(connfd,&readfds);
                    //2.更新maxfd
                    if (connfd + 1> nfds)
                        nfds = connfd+1;
                } 
				else   //创建 --- 子进程 或 线程
				{  //此时肯定是某个客户端对应的connfd的值
                    read(i,buf,sizeof(buf)); //从i中读值,
                                              //因为i表示的是当前就绪的文件描述符
					printf("buf == %s\n",buf);  
                }
            }
        }
    }
}

epoll

1.创建监控的epoll对象

epoll_create

① int epoll_create(int size);

功能:创建epoll对象,返回文件描述符

参数:@size 并不是限制了epoll所能监听的描述符最大个数,只是对内核初始分配内部数据结构的一个建议。

返回值:是Epoll描述符

epoll_ctl

  1. 所谓边沿触发,指的是对应fd从无数据到有数据这一瞬间的变化,而水平触发是指对应的fd中只要有数据就认为是就绪状态,直到数据处理完
  2. epoll如果监听ET事件,fd必须是非阻塞套接口(高性能场合)比如:监听可读事件,当ET上报可读后,需要一直读Fd直到遇到EAGATN错误为止,以免遗留数据在缓冲区中,如果FD是阻塞的,则会读到阻塞了(不建议做太多的耗时操作)
  3. 现在很多的高性能并发服务器:epoll+et+线程池

epoll_wait

相关推荐
曹牧28 分钟前
Spring:@RequestMapping注解,匹配的顺序与上下文无关
java·后端·spring
daixin884831 分钟前
cursor无法正常使用gpt5.5等模型解决方案
java·redis·cursor
AnalogElectronic1 小时前
linux 测试网络和端口是否连通的命令详解
linux·网络·php
韦禾水1 小时前
记录一次项目部署到tomcat的异常
java·tomcat
曦月合一2 小时前
树莓派安装jdk、tomcat、vnc、谷歌浏览器开机自启等环境配置
java·tomcat·树莓派
Edward111111112 小时前
4月28日防火墙问题
linux·运维·服务器
想学后端的前端工程师2 小时前
【补充内外网突然不通的情况】
运维·服务器
Rust研习社2 小时前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
此剑之势丶愈斩愈烈2 小时前
openssl 自建证书
java
面汤放盐2 小时前
何时使用以及何时不应使用微服务:没有银弹
java·运维·云计算