1. C++实现一个最简单的服务器和五种I/O模型

这只是一个简单的服务器,
server.h
这个里面就是实现一个Server的类。然后一个run方法

/**
 *Server class
 *@author lipu123
 *@date 2024-5-24
 */

#ifndef SERVER_H
#define SERVER_H
namespace avdance{

class Server{
public:
    Server();
    ~Server();
public:
    void run();
};

}

#endif // SERVER_H

server.cpp,这个里面实现了Server中的具体函数

/**
 *Server class
 *@author lipu123
 *@date 2024-5-24
 */


#include "server.h"
#include<iostream>
#include<unistd.h>

namespace avdance{

Server::Server() {
    std::cout<<"construct...."<<std::endl;
}
Server::~Server(){
    std::cout<<"destruct...."<<std::endl;
}
void Server::run(){
    while(1){
        std::cout<<"runing..."<<std::endl;
        ::usleep(1000000);//sleep one second
    }
    return ;
}
}

mian.cpp

#include<iostream>

#include "server.h"

int main(int argc,char* argv[]) {

    avdance::Server* server=new avdance::Server();

    if(server){
        server->run();
    }
    return 0;
}

五种 I/O 模型

先花费点时间了解这几种 I/O 模型,有助于后面的理解。

阻塞 I/O 与非阻塞 I/O

阻塞和非阻塞的概念能应用于所有的文件描述符,而不仅仅是socket。我们称阻塞的文件描述符为阻塞 I/O,称非阻塞的文件描述符为非阻塞I/O
socket在创建的时候默认是阻塞的,我们可以给socket系统调用的第 2 个参数传递 SOCK_NONBLOCK标志,或者通过fcntl系统调用的F_SETFL命令将其设置为非阻塞的。

  • 针对阻塞 I/O 执行的系统调用可能因为无法立即完成而被操作系统挂起,直到等待的事件发生为止。可能被阻塞的系统调用为acceptsendrecvconnect
  • 针对非阻塞I/O执行的系统调用则总是立即返回,而不管事件是否已经发生。如果事件没有立即发生,这些系统调用就返回-1,和出错的情况一样。此时我们必须根据errno来区分这两种情况。
    • acceptsendrecv而言,事件未发生时errno通常被设置为EAGAIN(意为“再来一次”)或者 EWOUDBLOCK(意为“期望阻塞”);
    • connect而言,errno则被设置成EINPROGRESS(意为“在处理中”)。

很显然,只有在事件已经发生的情况下操作非阻塞I/O(读、写等),才能提高程序的效率。因此,非阻塞I/O 通常要和其他I/O通知机制一起使用,比如I/O复用和SIGIO信号。

笔者认为,我们使用非阻塞I/O的最佳情况是:【当我们进行系统调用的时候,它所需要的事件已经发生了】,这样系统调用就不会被阻塞,直接进行处理。比如accept函数,I/O复用的好处就是当我们调用accept函数的时候,已经有客户端在请求连接,这样直接调用accept,提高运行效率。

I/O 复用

I/O 复用是一种 I/O 通知机制,而且是最常用的通知机制。

I/O 复用是指应用程序通过 I/O 复用函数(select、poll、epoll_wait)向内核注册一组事件,内核通过 I/O 复用函数把其中就绪的事件通知给应用程序。

需要注意的是 I/O 复用函数本身是阻塞的,它们能提高程序效率的原因在于它们具有同时监听多个 I/O 事件的能力。

信号驱动 I/O

为一个目标文件描述符指定宿主进程,那么被指定的宿主进程将捕获到 SIGIO 信号。这样,当文件描述符上有事件发生时,SIGIO 信号的信号处理函数将被触发,我们也就可以在该信号处理函数中对目标文件描述符执行非阻塞 I/O 操作了。

异步 I/O

理论上讲,阻塞 I/O、非阻塞 I/O、信号驱动 I/O 和 I/O 复用都是同步 I/O。

  • 同步I/O:内核向应用程序通知的是就绪事件,比如只通知有客户端连接,要求用户代码自动执行I/O操作(将数据从内核缓冲区读入用户缓冲区,或将数据从用户缓冲区写入内核缓冲区);
  • 异步I/O:内核向应用程序通知的是完成事件,比如读取客户端的数据之后才通知应用程序,由内核完成I/O操作(数据在内核缓冲区和用户缓冲区之间的移动是由内核在“后台”完成的)。

对异步 I/O 而言,用户可以直接对 I/O 执行读写操作,这些操作告诉内核用户读写缓冲区的位置,以及 I/O 操作完成之后内核通知应用程序的方式。异步 I/O 的读写操作总是立即返回,不论 I/O 是否是阻塞的,因为真正的读写操作已经由内核接管。

https://www.cnblogs.com/lafiteee/p/16222757.html

五种 I/O 模型

阻塞IO

阻塞IO指的是用户程序将IO请求提交后,无需等待IO操作的完成,而是可以继续处理别的事情。
所谓阻塞IO,是指以事件触发的机制来对IO操作进行处理。
与多进程和多线程技术相比,阻塞I/O技术的最大优势是系统开销小,系统不必创建进程/线程,也不必维护这些进程/线程,从而大大减小了系统的开销。
我们举个例子吧:
假如说我们要去读一个数据,我们要发生系统调用,然后去询问IO是否准备好了,
在这里插入图片描述
对于阻塞I/O,如果没有准备好的话,他就会一直等,一直等,直到他准备好了。然后再进行下一步操作。
在这里插入图片描述

非阻塞IO

对于非阻塞I/O,发起系统调用后,不是一直等,而是立即返回一个没准备好的I/O。
在这里插入图片描述
然后过一段时间这个用户态会再次询问是否准备好了。如果还是没有准备好,还是会立即返回,知道准备好了。
在这里插入图片描述
然后在一些空挡里面,这个CPU是可以干其他的事情的。

  1. 阻塞IO
    为了完成IO发起IO调用,若IO事件没有就绪,则一直等待,直到IO就绪,开始数据拷贝。
    优点:流程最为简单,使用复杂度非常低。
    缺点:IO效率较低,对资料利用不足。
    在这里插入图片描述
  2. 非阻塞IO
    为了完成IO发起IO调用,若IO事件没有就绪,则调用直接返回(返回后,先进行一些其他任务,之后再重新发起IO调用)。
    优点:不等待IO就绪,而是直接立即返回,可以继续对其他描述符进行IO操作,充分利用资源,效率相较于阻塞IO有所提高。
    缺点:IO不够实时,且通常需要循环进行操作,增加了一定的复杂度。
    在这里插入图片描述

异步IO

    发起IO调用,让系统进行IO就绪等待以及完成数据拷贝,完成后再通过信号通知进程。

注意:
(1)异步IO会告诉系统,需要对哪个描述符进行什么IO操作,要把IO操作的数据拷贝到哪块缓冲区,以及完成后通过什么信号通知进程。
(2)当进程收到信号,就表示IO已经完成,这时就可以直接对指定缓冲区中的数据进行处理。
优点:对系统资源利用非常高,效率也是最高。
缺点:流程复杂度也是最高。
在这里插入图片描述

同步阻塞:

  • 同步指的是程序按照顺序执行,每个操作都要等待前一个操作完成才能继续。
  • 阻塞表示当程序执行一个IO操作(如读取文件或网络请求)时,线程或进程会等待直到操作完成,期间无法执行其他任务。

例子:传统的阻塞式网络编程。当发送一个网络请求时,线程会阻塞在那里,直到接收到服务器的响应。

同步非阻塞:

  • 同步仍然是指按顺序执行,但是在等待IO操作完成时,线程不会被阻塞。
  • 非阻塞表示执行IO操作时,线程可以继续执行其他任务而不必等待IO操作完成。

例子:通过轮询方式检查资源是否可用,或者设置超时等待,如果资源还不可用就返回并继续执行其他任务。

异步阻塞:

  • 异步指的是不按照严格的顺序执行,而是通过事件驱动或回调等方式处理IO操作。
  • 阻塞在这里指的是IO操作执行时仍然会等待,但不会阻塞整个线程或进程,而是使用额外的线程或事件处理机制来处理IO。

例子:某些使用线程池的异步编程框架,当执行一个阻塞的IO操作时,会从线程池中获取一个线程执行IO操作,其他任务则可以继续使用线程池中的其他线程执行。

异步非阻塞:

  • 异步仍然是通过事件驱动或回调等方式处理IO操作。
  • 非阻塞表示执行IO操作时,不会等待IO操作完成,而是通过回调函数或事件通知的方式处理IO操作的结果。

例子:JavaScript中的异步操作,如使用Promise或回调函数处理异步请求,当发起一个异步网络请求时,JavaScript引擎可以继续执行其他任务,而不必等待网络请求返回结果。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值