Linux C++ 网络编程

前言
在上一节中以拆分的方式学习完 Linux 、C++、网络等知识后,这节会将这三个模块糅合起来,站在项目的基础上再次去学习这三个模块。 Linux 网路编程比较经典的有 Redis、Muduo、TeamTalk等开源项目。本文将以 Muduo 来介绍 网络编程的框架,学习完 Muduo 再去学习其他框架就容易许多了。注意, 文中贴的代码均为核心代码,且注释详细,认真阅读。
下载路径
github 地址: https://github.com/smilew12/muduo.git
项目结构
项目主要分为两个模块:
base 模块: 主要封装互斥锁、条件变量、线程池、日志等基础类;
net 模块: 主要根据 reactor 模型对 Linux 平台下 Epoll 的封装;
epoll 由来
先来说说传统的迭代式服务器模型以及一个连接一个线程的模型的缺点,以下图一个连接一个线程为例说明:

有图中可以看到,进程将阻塞在 accept 函数处,当客户端调用 connect 函数时,accept 返回,当前进程创建一个线程用来处理本次会话的任务。但是创建线程是有一定的开销的,在 32 位 Linux 系统下用户空间有 3G, 一个线程栈 10M, 那么总共可以创建 300 多个线程,同时切换线程也会有时间开销,所以并发连接数不会很高。
IO 多路复用的产生
有没有一种方式:
-
我将我想要监听的链接、读写等事件全权委托给它;
-
有连接到来事件的时候通知我? 我直接调用 accept 函数去接收。
-
有数据到来的时候也通知我? 我直接调用 recv 函数去收取数据。
-
发送缓冲区有空间时也通知我? 我直接调用 send 函数去发送数据。
为了解决这种相当于代理一样的东西,linux 内核给用户提供了一系列系统调用,当有事件时,该系统调用会返回相应事件,用户只需拿到事件进行处理即可。那么这就是 IO 多路复用函数(select / poll / epoll)
因为本文是将 Linux 平台下的网络编程,所以选择了 Epoll:
epoll_create() 函数用来创建一个代理对象;
epoll_wait() 函数就是当有事件到来时,会返回响应事件的代理;
epoll_ctl() 主要是往这个代理中注册你想要监听的事件;
下面是一个根据 Reactor 模型对 Epoll 的封装例子:
//头文件
//.cpp文件
