【sylar】框架篇-Chapter16-HttpSession 模块

本文介绍了一个基于C++编写的高性能分布式HTTP服务器框架,详细讲解了HttpSession类的设计,包括如何接收HTTP请求和发送HTTP响应。通过HttpRequestParser解析HTTP请求,并实现了HttpSession的内存管理。此外,还展示了基于该框架实现的小型示例和基于Redis的参数查询服务。

站在巨人的肩膀上

C++高性能分布式服务器框架

从零开始重写sylar C++高性能分布式服务器框架

概述

  • HttpSession 的封装。

HttpSession

  • 继承自 SocketStream。
  • 主要是接受 http 请求 recvRequest() 和 发送 http 响应 sendResponse() 两个方法。

部分相关代码

/**
 * @filename    http_session.h
 * @brief   HttpSession的封装
 * @author  L-ge
 * @version 0.1
 * @modify  2022-07-15
 */
#ifndef __SYLAR_HTTP_SESSION_H__
#define __SYLAR_HTTP_SESSION_H__

#include "sylar/streams/socket_stream.h"
#include "http.h"

namespace sylar
{

namespace http
{

class HttpSession : public SocketStream
{
public:
    typedef std::shared_ptr<HttpSession> ptr;

    /**
     * @brief   构造函数 
     *
     * @param   sock    Socket类型
     * @param   owner   是否托管
     */
    HttpSession(Socket::ptr sock, bool owner = true);

    /**
     * @brief   接受http请求
     */
    HttpRequest::ptr recvRequest();
    
    /**
     * @brief  发送http响应 
     *
     * @param   rsp http响应
     *
     * @return  >0 发送成功
     *          =0 对方关闭
     *          <0 Socket异常
     */
    int sendResponse(HttpResponse::ptr rsp);
};

}

}

#endif


#include "http_session.h"
#include "http_parser.h"

namespace sylar
{

namespace http
{

HttpSession::HttpSession(Socket::ptr sock, bool owner)
    : SocketStream(sock, owner)
{
}

HttpRequest::ptr HttpSession::recvRequest()
{
    HttpRequestParser::ptr parser(new HttpRequestParser);
    uint64_t buff_size = HttpRequestParser::GetHttpRequestBufferSize();
    std::shared_ptr<char> buffer(new char[buff_size], [](char* ptr){ delete[] ptr; });  // 自定义删除函数
    char* data = buffer.get();      // 虽然用了智能指针,但是使用的时候还是直接用裸指针
    int offset = 0;     // 偏移量,尚未解析完的数据
    // 先去理解parser->execute里面的memmove方法,再看这个do-while循环会比较容易理解
    do
    {
        int len = read(data + offset, buff_size - offset);  // 有offset个字节的数据尚未解析,因此偏移量是offset
        if(len <= 0)
        {
            close();
            return nullptr;
        }
        len += offset;                  // 加上上一次没解析完的数据,这次再一起解析
        size_t nparse = parser->execute(data, len); // 这里面有memmove的动作,所以是从data开始解析就行
        if(parser->hasError())
        {
            close();
            return nullptr;
        }
        offset = len - nparse;          // 尚未解析完成的数据
        if(offset == (int)buff_size)    // 尚未解析完的数据等于原始数据,相当于没解析成功一点东西,即失败
        {
            close();
            return nullptr;
        }
        if(parser->isFinished())
        {
            break;
        }
    } while(true);

    int64_t length = parser->getContentLength();    // 消息主体的长度(不包括http首部)
    if(length > 0)
    {
        std::string body;
        body.resize(length);
        
        int len = 0;
        if(length >= offset)
        {
            memcpy(&body[0], data, offset);
            len = offset;
        }
        else
        {
            memcpy(&body[0], data, length);
            len = length;
        }

        length -= offset;   // 减掉已经copy到body的长度
        if(length > 0)
        {
            if(readFixSize(&body[len], length) <= 0)
            {
                close();
                return nullptr;
            }
        }
        parser->getData()->setBody(body);
    }

    parser->getData()->init();  // 里面主要是初始化是否长连接
    return parser->getData();
}

int HttpSession::sendResponse(HttpResponse::ptr rsp)
{
    std::stringstream ss;
    ss << *rsp;             // 重载了<<运算符,输出的其实就是一个http报文了
    std::string data = ss.str();
    return writeFixSize(data.c_str(), data.size());
}

}

}

广告时间:基于sylar框架实现的小demo(希望给个star)

基于redis的参数查询服务

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值