HTTP连接处理详解
背景
服务器和核心功能是完成对HTTP请求报文的解析,并向客户端发出HTTP响应报文。在Httpconnection模块正是要完成上述的功能需求。
为了完成报文解析、资源定位、发送响应等功能需求,该项目一共是写了4个头文件,与此对应的就是4个模块:Httpconnection模块、Httprequest模块、Httpresponse模块以及Buffer缓冲区模块。四个模块之间的相互关系如下图所示
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWaMy8LW-1650472188539)(…/images/img1.png)]
Httpconnection类成员变量介绍
Httpconnection是对HTTP连接的抽象,在模块中要定义一些变量保存socket通信客户端的信息:(建立socket连接由其他模块负责,这里只负责通信和关闭通信)一条socket连接就需要一个Httpconnection模块,所以我们使用m_fd
唯一的标记它;并且使用m_isClose
判断连接是否被关闭,便于调用closeConn
关闭客户端连接。一个HTTP连接还需要读写数据,所以给每一个HTTP连接定义一个读缓冲区和一个写缓冲区。在解析请求和响应请求的时候,我们借助Httprequest和Httpresponse
完成,所以也需要各种定义一个这两种变量。
private:
int m_fd;
struct sockaddr_in m_addr; // 获取IP和port
bool isClose;
int m_iovCnt;
struct iovec m_iov[2]; // 用于分散写writev的结构体
Buffer m_readBuf;
Buffer m_writeBuf;
Httprequest m_request;
Httpresponse m_response;
此外,还定义了三个static静态成员:isET
, srcDir
, userCount
。类的静态成员不属于某一个类对象,是属于整个类的,所有的类对象都可以访问该静态成员。
isET
布尔变量表征所有的Httpconnection对象是否在使用epoll的ET边缘触发模式。
srcDir
定位资源的根路径
userCount
是当前连接的数量。由于对该变量有多线程读取和写入,需要作线程保护。我们可以使用std::atomic对变量进行线程保护
public:
static bool isET;
static const char *srcDir;
static std::atomic<int> userCount;
Httpconnection任务流程介绍
成员变量的介绍到这里就结束了。下面对Httpconnection模块的执行流程作一个介绍:
完成工作任务的主要是3个函数:
ssize_t readBuffer(int *saveErrno);
bool handleHTTPConn();
ssize_t writeBuffer(int *saveErrno);
readBuffer
函数从m_fd对应的socket中读取数据,由于在Buffer缓冲区中我们已经定义好了读取函数recvFd
,这里只是简单的对该函数进行封装即可。读取到的HTTP请求报文会保存在之前定义的读取缓冲m_readBuf
handlerHTTPConn
整