HTTP连接(读取请求+解析请求+生成响应+回送响应)
创始人
2024-05-11 00:23:00
0

一个HTTP连接的功能就是:读取请求+解析请求+生成响应+回送响应

解析HTTP请求报文(GET、POST)完成了读取请求+解析请求的两步;

生成HTTP响应报文 完成了生成响应的一步;

所以本文首先要实现回送响应的部分,然后将这四步有序组织起来。

首先是回送响应:

因为生成请求的部分将响应头置于缓冲区buffer内,将响应体即要回送的文件,通过mmap方式建立了内存映射,获得一个指向被映射区的指针char* mmFile。

通过writev方法,将两块内存中的数据集中写至socket中,发往客户端

  1. 给struct iovec vec[2] 赋值,vec[0]保存响应头的首地址和长度,vec[1]保存响应体的首地址和长度

    response.makeResponse(writeBuff);//响应头vec[0].iov_base=const_cast(writeBuff.peek());vec[0].iov_len=writeBuff.readableBytes();iovCnt=1;//响应体if(response.getFileLen()>0&&response.getfile()){vec[1].iov_base=response.getfile();vec[1].iov_len=response.getFileLen();iovCnt=2;}
  1. 使用writev函数向socket内写入响应报文

ssize_t HttpConn::write(int* errno_)
{ssize_t len=-1;while (true){len=writev(fd,vec,iovCnt);if(len<0)//出错{*errno_=errno;break;}if(vec[0].iov_len+vec[1].iov_len==0)//全部写完 { break; }if(static_cast(len)>vec[0].iov_len){vec[1].iov_base=(uint8_t*)vec[1].iov_base+(len-vec[0].iov_len);vec[1].iov_len-=(len-vec[0].iov_len);if(vec[0].iov_len){writeBuff.retrieveAll();vec[0].iov_len=0;}}else{vec[0].iov_base=(uint8_t*)vec[0].iov_base+len;vec[0].iov_len-=len;writeBuff.retrieve(len);}}return len;   
}

其次是组织读取请求+解析请求+生成响应+回送响应这四步:

通过ssize_t HttpConn::read(int* errno_) +bool HttpConn::process()函数+上面的ssize_t HttpConn::write(int* errno_)函数完成。

/*从客户端读取请求至readBuff内*/
ssize_t HttpConn::read(int* errno_)
{ssize_t len=-1;while(true){len=readBuff.readFd(fd,errno_);if(len<=0)break;}return len;
}
/*解析客户端请求,生成Http响应报文*/
bool HttpConn::process()
{request.init();//初始化Http请求if(readBuff.readableBytes()<=0){return false;}if(request.parse(readBuff))//解析Http请求成功{LOG_DEBUG("%s", request.getPath().c_str());//初始化Http响应,状态码为200response.init(srcDir,request.getPath(),request.isKeepAlive(),200);}else//解析Http请求失败{//初始化Http响应,状态码为400response.init(srcDir,request.getPath(),false,400);}response.makeResponse(writeBuff);//生成Http响应报文/*给struct iovec vec[2]赋值,vec[0]保存响应头的首地址和长度,vec[1]保存响应体的首地址和长度*///响应头vec[0].iov_base=const_cast(writeBuff.peek());vec[0].iov_len=writeBuff.readableBytes();iovCnt=1;//响应体if(response.getFileLen()>0&&response.getfile()){vec[1].iov_base=response.getfile();vec[1].iov_len=response.getFileLen();iovCnt=2;}return true;
}

HttpConn类结构 httpconn.h

#ifndef HTTPCONN_H
#define HTTPCONN_H#include
#include
#include #include "../log/log.h"
#include "../pool/sqlconnpool.h"
#include "../buffer/buffer.h"
#include "httprequest.h"
#include "httpresponse.h"class HttpConn
{
public:HttpConn();~HttpConn();void init(int connfd,const sockaddr_in& sockAddr);ssize_t read(int* errno_);//从客户端读取请求bool process();//解析请求+生成响应ssize_t write(int* errno_);//向客户端写响应void closeConn();//关闭Http连接const sockaddr_in& getSockAddr() const;int getFd() const;int getPort() const;const char* getIP() const;bool isKeepAlive() const;bool isWriteOver() const;static std::atomic userCount;//原子类型,保证多线程修改userCount时的正确性static const char* srcDir;
private:int fd;struct sockaddr_in addr;bool isClose;int iovCnt;struct  iovec vec[2];Buffer readBuff;Buffer writeBuff;HttpRequest request;HttpResponse response;
};#endif //! HTTPCONN__H

HttpConn类实现 httpconn.cpp

#include "httpconn.h"std::atomic HttpConn::userCount;
const char* HttpConn::srcDir=nullptr;HttpConn::HttpConn()
{fd=-1;addr={0};isClose=true;Log::getInstance()->init();
}HttpConn::~HttpConn()
{closeConn();
}void HttpConn::closeConn()
{response.unmapFile();if(isClose==false){isClose=true;userCount--;close(fd);LOG_INFO("Client (%s:%d) quit, userCount:%d",getIP(),getPort(),static_cast(userCount));}
}void HttpConn::init(int connfd,const sockaddr_in& sockAddr)
{assert(connfd>0);userCount++;fd=connfd;addr=sockAddr;readBuff.retrieveAll();writeBuff.retrieveAll();isClose=false;LOG_INFO("Client (%s:%d) in, userCount:%d",getIP(),getPort(),static_cast(userCount));
}const sockaddr_in& HttpConn::getSockAddr() const
{return addr;
}
int HttpConn::getFd() const
{return fd;
}
int HttpConn::getPort() const
{return addr.sin_port;
}
const char* HttpConn::getIP() const
{return inet_ntoa(addr.sin_addr);
}
bool HttpConn::isKeepAlive() const
{return request.isKeepAlive();
}
bool HttpConn::isWriteOver() const
{return vec[0].iov_len+vec[1].iov_len==0;
}ssize_t HttpConn::read(int* errno_)
{ssize_t len=-1;while(true){len=readBuff.readFd(fd,errno_);if(len<=0)break;}return len;
}ssize_t HttpConn::write(int* errno_)
{ssize_t len=-1;while (true){len=writev(fd,vec,iovCnt);if(len<0){*errno_=errno;break;}if(vec[0].iov_len+vec[1].iov_len==0) { break; }if(static_cast(len)>vec[0].iov_len){vec[1].iov_base=(uint8_t*)vec[1].iov_base+(len-vec[0].iov_len);vec[1].iov_len-=(len-vec[0].iov_len);if(vec[0].iov_len){writeBuff.retrieveAll();vec[0].iov_len=0;}}else{vec[0].iov_base=(uint8_t*)vec[0].iov_base+len;vec[0].iov_len-=len;writeBuff.retrieve(len);}}return len;   
}bool HttpConn::process()
{request.init();if(readBuff.readableBytes()<=0){return false;}if(request.parse(readBuff)){LOG_DEBUG("%s", request.getPath().c_str());response.init(srcDir,request.getPath(),request.isKeepAlive(),200);}else{response.init(srcDir,request.getPath(),false,400);}response.makeResponse(writeBuff);//响应头vec[0].iov_base=const_cast(writeBuff.peek());vec[0].iov_len=writeBuff.readableBytes();iovCnt=1;//响应体if(response.getFileLen()>0&&response.getfile()){vec[1].iov_base=response.getfile();vec[1].iov_len=response.getFileLen();iovCnt=2;}return true;
}

相关内容

热门资讯

关于唱歌比赛主持词   主持词是指主持人在主持节目的过程中进行节目串联的串联词,一般由开场白、中间部分与结束语组成。以下...
动漫感人台词 动漫感人台词(通用175句)  台词可以刻画人物的性格,表现人物的感情,加强剧情的表现力。那些广为流...
最新年会主持词 最新年会主持词(精选11篇)  契合现场环境的主持词能给集会带来双倍的效果。在如今这个时代,主持人的...
新生文艺汇演主持词 新生文艺汇演主持词  主持词要根据活动对象的不同去设置不同的主持词。在当今社会生活中,各种集会的节目...
家长代表幼儿园毕业典礼主持词 家长代表幼儿园毕业典礼主持词  主持词是各种演出活动和集会中主持人串联节目的串联词。在人们积极参与各...
学校元旦晚会主持词开场白和结... 学校元旦晚会主持词开场白和结束语  2017年元旦晚会主持词怎么写?怎么开场比较好呢?结束语又该怎么...
毕业晚会致辞 毕业晚会致辞(精选18篇)  在学习、工作或生活中,大家都写过致辞吧,致辞要求风格的雅、俗、庄、谐要...
幼儿园六一节目串词 幼儿园六一节目串词红黄蓝幼第一文库网儿园节目串词主持人(师):亲爱的家长朋友们( ):敬爱的老师们(...
祝寿主持词 祝寿主持词  主持词要尽量增加文化内涵、寓教于乐,不断提高观众的文化知识和素养。在人们积极参与各种活...
回门宴主持词 让你的回门宴顺... 回门宴主持词 让你的回门宴顺利完成  篇一:新婚回门宴主持词  亲爱的各位来宾,各位亲朋好友,先生们...
结婚新郎致辞 结婚新郎致辞(15篇)  在学习、工作、生活中,说到致辞,大家肯定都不陌生吧,致辞具有能伸能缩,可以...
庆中秋迎国庆联欢晚会主持词(...   (念8条短信)  男:我们的驻外营销健儿发来的每一条祝福都是那么的感人。由于时间关系,我们不能一...
重庆森林经典台词 重庆森林经典台词  《重庆森林》由两个基本不相干的故事构成。两个故事之间的关系,就像擦身而过的金城武...
歌曲奔跑主持词串词 歌曲奔跑主持词串词范文  借鉴诗词和散文诗是主持词的一种写作手法。在如今这个中国,主持成为很多活动不...
年会老板感谢员工精彩致辞 年会老板感谢员工精彩致辞(通用16篇)  在日复一日的学习、工作或生活中,大家都用到过致辞吧,致辞具...
六一文艺汇演主持词 六一文艺汇演主持词(通用10篇)  主持词要根据活动对象的不同去设置不同的主持词。在人们积极参与各种...
文艺晚会主持稿   男:今晚,我们再次欢聚一堂  女:满载丰收的喜悦,用歌舞表达内心最真挚的情感  男:朋友们,古往...
最新公司年会主持词 最新公司年会主持词  主持词已成为各种演出活动和集会中不可或缺的一部分。在当下的社会中,主持词的实用...
毕业晚会主持词结束语 毕业晚会主持词结束语  以下是由应届毕业生网PQ小编为大家整理出来的2016年毕业晚会主持词结束语,...
启动会主持词 启动会主持词  利用在中国拥有几千年文化的诗词能够有效提高主持词的感染力。在现在的社会生活中,主持人...