brynet源码阅读——http组件和wrapper组件

0、引言

在前面的文章中介绍了brynet网络库中的各个组件,在这篇文章中介绍wrapper组件和http组件。其中wrapper组件是给用户使用使用的封装接口,用户只需要简单设置一些参数就可以搭建一个网络服务器或者客户端。而http组件是brynet中http部分的关键部分,依赖于开源的http_parser.h模块。

1、wrapper组件

1.1、ConnectionBuilder.hpp

该文件中封装了建立会话连接的Builder器,提供了一些简单的接口,用来给用户设置一些配置,设置完了配置可以直接调用asyncConnect启动连接。示例代码如下:

cpp 复制代码
wrapper::ConnectionBuilder connectionBuilder;
    connectionBuilder
            .WithService(service)
            .WithConnector(connector)
            .WithMaxRecvBufferSize(1024 * 1024)
            .AddEnterCallback(enterCallback);

1.2、HttpConnectionBuilder.hpp

这个类在ConnectionBuilder的基础上封装了一个专门用做Http会话连接的Builder类,看懂了ConnectionBuilder.hpp中的实现,这个文件中的类就是又封装了一层,比较简单。使用方法如下:

cpp 复制代码
 wrapper::HttpConnectionBuilder()
                .WithConnector(connector)
                .WithService(service)
                .WithAddr("14.215.177.39", 80)
                .WithTimeout(std::chrono::seconds(10))
                .WithFailedCallback([]() {
                    std::cout << "connect failed" << std::endl;
                })
                .WithMaxRecvBufferSize(1000)
                .WithEnterCallback([requestStr](const HttpSession::Ptr& session, HttpSessionHandlers& handlers) {
                    (void) session;
                    std::cout << "connect success" << std::endl;
                    session->send(requestStr);
                    handlers.setHttpBodyCallback([](const HTTPParser& httpParser,
                                                    const HttpSession::Ptr& session,
                                                    const char* body,
                                                    size_t length) {
                        (void) httpParser;
                        (void) session;
                        (void) body;
                        (void) length;
                    });
                    handlers.setHeaderCallback([](const HTTPParser& httpParser,
                                                  const HttpSession::Ptr& session) {
                        (void) httpParser;
                        (void) session;
                    });
                    handlers.setHttpEndCallback([](const HTTPParser& httpParser,
                                                   const HttpSession::Ptr& session) {
                        (void) session;
                        // because has call setHttpBodyCallback, so the body from http parser is empty.
                        std::cout << httpParser.getBody() << std::endl;
                        counter.fetch_add(1);
                        std::cout << "counter:" << counter.load() << std::endl;
                        session->postClose();
                    });
                })
                .asyncConnect();

1.3、HttpServiceBuilder.hpp

在ListenerBuilder的基础上封装了一层专门建立HttpService的Build器,只要理解了ListenerBuilder的原理,这里的代码非常简单。使用方法如下:

cpp 复制代码
wrapper::HttpListenerBuilder listenBuilder;
    listenBuilder
            .WithService(service)
            .AddSocketProcess([](TcpSocket& socket) {
                socket.setNodelay();
            })
            .WithMaxRecvBufferSize(1024)
            .WithAddr(false, "0.0.0.0", port)
            .WithReusePort()
            .WithEnterCallback([httpEnterCallback, wsEnterCallback](const HttpSession::Ptr& httpSession, HttpSessionHandlers& handlers) {
                handlers.setHttpEndCallback(httpEnterCallback);
                handlers.setWSCallback(wsEnterCallback);
            })
            .asyncRun();

1.4、ServiceBuilder.hpp

该文件中定义了建立服务的Builder类,监听线程和工作线程可以是1:1,也可以是1:n,这取决于mTcpService指向对象的类型,关键的成员函数理解如下:

cpp 复制代码
// 服务器中真正的worker service,这里面都是监听的通信socket
ITcpService::Ptr mTcpService;
// 会话建立成功需要执行的callback
std::vector<ListenThread::TcpSocketProcessCallback> mSocketProcessCallbacks;
// 建立会话的参数
ConnectionOption mSocketOption;
// 监听的ip地址
std::string mListenAddr;
// 监听的端口
int mPort = 0;
bool mIsIpV6 = false;
bool mEnabledReusePort = false;
// 监听线程
ListenThread::Ptr mListenThread;

2、http组件

2.1、http_parser.h

这部分是开源的库,用来解析Http的请求命令和响应命令,这部分代码还没有仔细研究,使用方法和其他的库类似,都是通过一些callback将解析到的数据保存到自己定义的数据结构中。

2.2、HttpFormat.hpp

该文件中定义了两个关键类,一个是HttpRequest、一个是HttpResponse。其中HttpRequest是Http请求的结构体,在发送请求之前,创建一个对象,并通过提供的接口设置参数,最后通过getResult() 接口获得Http请求指令的字符串,这样就可以通过通信套接字发送出去。同理,HttpResponse是响应的Http指令。网络库中定义这两个类是常见做法。

2.3、HttpParser.hpp

该文件中定义了HTTPParser类,http解析类,借助开源的http_parser.h,核心思想是将接收到的字符串利用http_parser.h将其解析并将解析出来的内容利用callback的形式放到类的成员变量中,并且会执行对应的callback函数。brynet在制作返回的HttpResponse时是在callback函数中做的,并不像sylar框架那样,callback中只将命令分解出来,真正的做请求响应动作是在serverlet中做的。下面介绍下各个成员变量的含义:

cpp 复制代码
// http_parser中的数据结构
const http_parser_type mParserType;
http_parser mParser;
// 解析的时候用到的callback
http_parser_settings mSettings;
// 方法
int mMethod = -1;
bool mIsUpgrade = false;
bool mIsWebSocket = false;
// 链接是否alive
bool mIsKeepAlive;
// 解析是否结束
bool mISCompleted;
// 下面这些成员变量主要用于存储解析出来的数据
std::string mPath;
std::string mQuery;
std::string mStatus;
std::map<std::string, std::string> mHeadValues;
int mStatusCode;
// 存放解析出来的url、body
std::string mUrl;
std::string mBody;
// websocket相关的
std::string mWSCacheFrame;
std::string mWSParsePayload;
WebSocketFormat::WebSocketFrameType mWSFrameType;
// 解析完头需要执行的callback
std::function<void()> mHeaderCallback;
// 解析完body需要执行的callback
std::function<void(const char*, size_t)> mBodyCallback;
// 解析完成需要执行的callback,可以将HttpResponse的拼装放到这里面做
std::function<void()> mMsgEndCallback;

2.4、HttpService.hpp

该文件中定义了3个类,Http会话类HttpSession、Http会话类相关的callback函数和HttpService类。HttpService类中的关键函数代码如下

cpp 复制代码
static void setup(const TcpConnection::Ptr& session,
                      const HttpSession::EnterCallback& enterCallback)
{
    if (enterCallback == nullptr)
    {
        throw BrynetCommonException("not setting http enter callback");
    }

    auto httpParser = std::make_shared<HTTPParser>(HTTP_BOTH);
    auto httpSession = HttpSession::Create(session);

    HttpSessionHandlers handlers;
    // 这里一般会往handlers中设置一些回调函数,等到解析器解析到对应的数据后,才会执行对应的callback函数
    enterCallback(httpSession, handlers);
    httpSession->setClosedCallback(std::move(handlers.mCloseCallback));
    httpSession->setWSCallback(std::move(handlers.mWSCallback));
    httpSession->setWSConnected(std::move(handlers.mWSConnectedCallback));
    // 设置callback到httpParser
    auto headerCB = handlers.mHttpHeaderCallback;
    if (headerCB != nullptr)
    {
        httpParser->setHeaderCallback([=]() {
            headerCB(*httpParser, httpSession);
        });
    }

    auto bodyCB = handlers.mHttpBodyCallback;
    if (bodyCB != nullptr)
    {
        httpParser->setBodyCallback([=](const char* body, size_t length) {
            bodyCB(*httpParser, httpSession, body, length);
        });
    }
    // 一般在这里的callback会组装HttpResponse
    auto endCB = handlers.mHttpEndCallback;
    if (endCB != nullptr)
    {
        httpParser->setEndCallback([=]() {
            endCB(*httpParser, httpSession);
        });
    }
    // 这里也是设置callback函数
    HttpService::handle(httpSession, httpParser);
}
相关推荐
叫醒你笛莎1 分钟前
IGMP(Internet Group Management Protocol)与组播技术深度解析
网络
网络抓包与爬虫3 分钟前
Wireshark——抓包分析
websocket·网络协议·tcp/ip·http·网络安全·https·udp
lulinhao8 分钟前
HCIA/HCIP基础知识笔记汇总
网络·笔记
暴走的YH23 分钟前
【网络协议】三次握手与四次挥手
网络·网络协议
yuzhangfeng25 分钟前
【云计算物理网络】数据中心网络架构设计
网络·云计算
zhu12893035561 小时前
网络安全的重要性与防护措施
网络·安全·web安全
仙女很美哦1 小时前
Flutter视频播放、Flutter VideoPlayer 视频播放组件精要
websocket·网络协议·tcp/ip·http·网络安全·https·udp
网络研究院1 小时前
ChatGPT 的新图像生成器非常擅长伪造收据
网络·人工智能·安全·chatgpt·风险·技术·欺诈
路由侠内网穿透2 小时前
本地部署开源流处理框架 Apache Flink 并实现外部访问
大数据·网络协议·tcp/ip·flink·服务发现·apache·consul
Amos_ FAT2 小时前
关于串口协议的一点知识
经验分享·网络协议