一起写服务器(C++/线程池/多反应堆(类介绍下))
1.WorkerThread类
C++里面使用线程的话,线程/锁/条件变量对应头文件分别是thread/mutex/condition_variable
析构函数的内容可写可不写,反正运行期间子线程也是需要保存着,一直使用的
2.ThreadPoll类
可以使用vector来装子线程,C语言版本是用WorkerThread* ,就是指针用来存储,没有vector好用
3.HttpRequest类
3.1 请求头
我们知道,请求头分为key和value,在C语言版本只能用结构体构造键值对,C++里面可以直接使用map
addHeader函数可以直接使用map的insert
getHeader函数可以直接使用map的find
3.2 解析请求行里的function和bind
这里的bind是可调用对象绑定器
3.2.0 可调用对象
什么是可调用对象?
1.函数指针 比如int (*func)(int, double)
2.一个具有operator()成员函数的类对象(仿函数)
3.是一个可被转换为函数指针的类对象
4.一个类成员函数指针或者类成员指针
3.2.1 可调用对象包装器
std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象
用法:
std::function<返回值类型(参数类型列表)> diy_name = 可调用对象;
作用:
函数指针只能可以调用普通函数和类里面的静态函数(只要函数被定义出来了,就是存在了)
但是类里面的普通成员函数只有当类被创建出来才存在。所以引出了可调用对象包装器
可调用对象进行包装,得到一个统一格式,包装完成得到的对象相当于一个函数指针。
3.2.2 可调用对象绑定器
这里先解释一个C++11新特性,std::bind:(可调用函数绑定器)
std::bind用来将可调用对象与其参数一起进行绑定。绑定后的结果可以使用std::function进行保存,并延迟调用到任何我们需要的时候。通俗来讲,它主要有两大作用:
1.将可调用对象与其参数一起绑定成一个仿函数。
2.将多元(参数个数为n,n>1)可调用对象转换为一元或者(n-1)元可调用对象,即只绑定部分参数。
this是类实例对象地址,后面那个placeholders::_1是占位符,它对应传递函数的第一个参数,代表这个位置将在函数调用时被传入的第一个参数所替代。
3.2.3bind和function
可调用对象包装器 std::function 是不能实现对类成员函数指针或者类成员指针的包装的,但是通过绑定器 std::bind 的配合之后,就可以完美的解决这个问题(function啥都能用就是不能用类成员,但是bind可以带类参数,双剑合璧了属于是)
3.3解析请求头
CRLF那个函数是用来找每行结束符的,就是保存一行数据。下面进入循环后,找到 ":",前后分隔,前面是key,后面是value。然后addHeader,解析完了就跳过空行,设置已经处理完毕的状态。
4.HttpResponse类
同理响应头里面也有响应的键值对,用map处理即可。
4.1发送数据函数
喜闻乐见的老朋友可调用对象包装器,这货是在HttpRequest类里面指定的,根据请求类型,会设置成SendDir或者SendFile。
4.2添加回应头/组织http响应数据
同添加请求头/添加状态行,响应头,空行,最下面用sendDataFunc进行操作。
5.TcpConnection类
所有的类几乎都在里面了
5.1构造函数
new一切 并且 addTask,告知有新的连接到来
5.2连接问题
在回应客户端请求后,服务器会主动结束联系,这个写在了ProcessRead里面
6.Buffer类
就一点,我们这个程序优点之一,写一点读一点,这样可以使得Buffer的空间设置可以不用过大。
下篇文章再捋一下整体流程,并做一下压测。
#C/C++##C++##C++工程师##嵌入式##嵌入式工程师#