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

相关内容

热门资讯

常用商务英语口语   商务英语是以适应职场生活的语言要求为目的,内容涉及到商务活动的方方面面。下面是小编收集的常用商务...
六年级上册英语第一单元练习题   一、根据要求写单词。  1.dry(反义词)__________________  2.writ...
复活节英文怎么说 复活节英文怎么说?复活节的英语翻译是什么?复活节:Easter;"Easter,anniversar...
2008年北京奥运会主题曲 2008年北京奥运会(第29届夏季奥林匹克运动会),2008年8月8日到2008年8月24日在中华人...
英语道歉信 英语道歉信15篇  在日常生活中,道歉信的使用频率越来越高,通过道歉信,我们可以更好地解释事情发生的...
六年级英语专题训练(连词成句... 六年级英语专题训练(连词成句30题)  1. have,playhouse,many,I,toy,i...
上班迟到情况说明英语   每个人都或多或少的迟到过那么几次,因为各种原因,可能生病,可能因为交通堵车,可能是因为天气冷,有...
小学英语教学论文 小学英语教学论文范文  引导语:英语教育一直都是每个家长所器重的,那么有关小学英语教学论文要怎么写呢...
英语口语学习必看的方法技巧 英语口语学习必看的方法技巧如何才能说流利的英语? 说外语时,我们主要应做到四件事:理解、回答、提问、...
四级英语作文选:Birth ... 四级英语作文范文选:Birth controlSince the Chinese Governmen...
金融专业英语面试自我介绍 金融专业英语面试自我介绍3篇  金融专业的学生面试时,面试官要求用英语做自我介绍该怎么说。下面是小编...
我的李老师走了四年级英语日记... 我的李老师走了四年级英语日记带翻译  我上了五个学期的小学却换了六任老师,李老师是带我们班最长的语文...
小学三年级英语日记带翻译捡玉... 小学三年级英语日记带翻译捡玉米  今天,我和妈妈去外婆家,外婆家有刚剥的`玉米棒上带有玉米籽,好大的...
七年级英语优秀教学设计 七年级英语优秀教学设计  作为一位兢兢业业的人民教师,常常要写一份优秀的教学设计,教学设计是把教学原...
我的英语老师作文 我的英语老师作文(通用21篇)  在日常生活或是工作学习中,大家都有写作文的经历,对作文很是熟悉吧,...
英语老师教学经验总结 英语老师教学经验总结(通用19篇)  总结是指社会团体、企业单位和个人对某一阶段的学习、工作或其完成...
初一英语暑假作业答案 初一英语暑假作业答案  英语练习一(基础训练)第一题1.D2.H3.E4.F5.I6.A7.J8.C...
大学生的英语演讲稿 大学生的英语演讲稿范文(精选10篇)  使用正确的写作思路书写演讲稿会更加事半功倍。在现实社会中,越...
VOA美国之音英语学习网址 VOA美国之音英语学习推荐网址 美国之音网站已经成为语言学习最重要的资源站点,在互联网上还有若干网站...
商务英语期末试卷 Part I Term Translation (20%)Section A: Translate ...