这只是一个简单的服务器,
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 执行的系统调用可能因为无法立即完成而被操作系统挂起,直到等待的事件发生为止。可能被阻塞的系统调用为
accept
、send
、recv
和connect
; - 针对非阻塞
I/O
执行的系统调用则总是立即返回,而不管事件是否已经发生。如果事件没有立即发生,这些系统调用就返回-1
,和出错的情况一样。此时我们必须根据errno
来区分这两种情况。- 对
accept
、send
、recv
而言,事件未发生时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