1. HTTP连接处理流程

一个HTTP连接要完成的任务:

  1. 从sockFd中接收请求报文
  2. 解析请求报文
  3. 生成响应报文
  4. 向sockFd中发送响应报文

2. HTTP连接类实现

class HttpConn
{
private:
    int m_fd;
    struct sockaddr_in m_addr;
    bool m_isClosed;
    int m_iovCnt;
    struct iovec m_iov[2];
    Buffer m_readBuff;
    Buffer m_writeBuff;
    HttpResponse m_response;
    HttpRequest m_request;

public:
    static bool isET;
    static const char *srcDir;
    /*原子对象的主要特征是,从不同的线程访问这个包含的值不会导致数据竞争
     *(即,这样做是明确定义的行为,访问正确排序)*/
    static std::atomic<int> userCount;

    HttpConn();
    ~HttpConn();
    void Close();
    int GetFd() const;
    sockaddr_in GetAddr() const;
    const char *GetIP() const;
    int GetPort() const;
    /*初始化*/
    void Init(int sockFd, const sockaddr_in &addr);
    /*解析接收的请求报文,并准备响应报文*/
    bool Process();
    /*从m_fd中接收数据*/
    ssize_t Read(int *saveErrno);
    /*往m_fd中发送数据*/
    ssize_t Write(int *saveErrno);
    int ToWriteBytes() {
        return m_iov[0].iov_len + m_iov[1].iov_len;
    }
};

该类有两个缓冲区:

解析请求报文

m_request.Parse(m_readBuff) ,从读缓冲区读取请求报文并解析

生成响应报文

m_response.Respond(m_writeBuff) ,将生成的响应报文放入写缓冲区

HttpConn的读写:

这里的Read()需要将请求报文的内容读取到读缓冲区里面来,这样m_request才能够解析报文。

然后是Write(),这里主要是使用了writev()连续写来将写缓冲区中的响应报文写到socket中。

3. 集中写

注意由于生成响应报文的响应正文里面只是生成了Content-length并没有将文件也放进缓冲区,因为如果文件太大,缓冲区可能会装不下。所以我们在传输的时候,采用了集中写的方式,一块传输buff里面的内容另一块传输内存映射的文件指针