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;
}

相关内容

热门资讯

答谢会主持词 答谢会主持词15篇  主持词要根据活动对象的不同去设置不同的主持词。随着中国在不断地进步,主持人在活...
年会游戏主持词 年会游戏主持词  主持词没有固定的格式,他的最大特点就是富有个性。在人们积极参与各种活动的今天,主持...
《我是女王》经典台词及剧情介... 《我是女王》经典台词及剧情介绍  一、经典台词  一个偶尔会消失的男人,总有一天会永远的消失。  女...
追梦的主持串词 关于追梦的主持串词  篇一:梦想串词  各位老师,大家好:  又到了一个追梦的季节。春之漫妙、夏之热...
生日宴会精彩致辞 生日宴会精彩致辞(精选5篇)  在日常学习、工作抑或是生活中,大家都不可避免地会接触到致辞吧,致辞是...
暨迎元旦合唱比赛主持词 暨迎元旦合唱比赛主持词  主持词没有固定的格式,他的最大特点就是富有个性。在当下这个社会中,很多场合...
六一主持词开场白和结束语 六一主持词开场白和结束语(精选9篇)  主持词是各种演出活动和集会中主持人串联节目的串联词。在如今这...
国学大讲堂主持词 国学大讲堂主持词  (开场语)同学们老师们:  大家下午好!在各方的积极努力下,国学大讲堂终于以全新...
文艺汇演主持词优秀 文艺汇演主持词优秀  主持词要注意活动对象,针对活动对象写相应的主持词。在当下这个社会中,主持人在活...
《老爸快跑》里的经典台词 《老爸快跑》里的经典台词  《老爸快跑》是由高一功执导,张云宵编剧,徐峥、伊春德主演的电视剧,于20...
公司领导年会致辞 公司领导年会致辞  在日常学习、工作和生活中,大家或多或少都用到过致辞吧,致辞要求风格的雅、俗、庄、...
秋季开学典礼主持词 秋季开学典礼主持词(精选6篇)  主持词已成为各种演出活动和集会中不可或缺的一部分。在一步步向前发展...
当幸福来敲门经典台词 当幸福来敲门经典台词大全  在日新月异的现代社会中,我们都可能会用到台词,台词可以刻画人物的性格,表...
六一儿童节开幕致辞 六一儿童节开幕致辞(通用5篇)  在日常的学习、工作、生活中,大家一定都接触过致辞吧,致辞要求风格的...
春晚主持词 春晚主持词(精选11篇)  主持词要根据活动对象的不同去设置不同的主持词。随着社会一步步向前发展,各...
小学国庆节主题活动主持词 小学国庆节主题活动主持词  主持词是主持人在节目进行过程中用于串联节目的串联词。在当下的社会中,活动...
八年级班会主持词 八年级班会主持词  主持词要注意活动对象,针对活动对象写相应的主持词。在如今这个中国,活动集会越来越...
职工追悼词 职工追悼词 各位亲友、各位来宾:  今天我们怀着十分沉痛的心情深切悼念退休职工×××。  ×××因病...
春天活动主持词 春天活动主持词  大家上午好!  踏着春天的脚步,踩着春风的节拍,春天已经来到我们中间,春天是生命的...
幼儿园家长会园长致辞 幼儿园家长会园长致辞幼儿园家长会园长致辞亲爱的家长、老师们:首先感谢大家在百忙中抽空参加今天举行的家...