Mongoose6.0源码分析(2)-http数据处理

http_handle开始新的旅程(老吴analyze_request


调用1:

mg_parse_http :处理请求包和应答包的头部

   {

    get_request_len:得到http包头状态行的长度,不包括body。

    mg_skip计算了请求行各标记的长度,不计空格

     [  

     

//请求包

    s = mg_skip(s, end, " ", &hm->method);//将method的长度存储在hm->method.len,并把s指到uri的第一位,并将hm->method.p指在起始位置
    s = mg_skip(s, end, " ", &hm->uri);
    s = mg_skip(s, end, "\r\n", &hm->proto);

应答包

    s = mg_skip(s, end, " ", &hm->proto);//协议处理

    hm->resp_code = atoi(s);//转换应答码

   s = mg_skip(s, end, "\r\n", &hm->resp_status_msg);//即 OK

    ]

    parse_http_headers:处理包头键值对,存储在array(header_names,header_value)中,通过Content-Length键值读取body长度body.len。

    req->message.len = len + req->body.len; //获得了总长度

   }


调用2: (s = mg_get_http_header(&hm, "Transfer-Encoding")) != NULL &&
        mg_vcasecmp(s, "chunked") == 0) {

    {

   这里是判断是否存在Transfer-Encoding键,及值是否为chunked;

  传输数据编码:Transfer-Encoding 
  数据编码,即表示数据在网络传输当中,使用怎么样的保证方式来保证数据是安全成功地传输处理。可以是分段传输,也可以是不分段,直接使用原数据进行传输。 
  有效的值为:Trunked和Identity. 

     }

调用3:mg_handle_chunked 处理分块传输 处理分块传输的数据(如果有的话)

  

   

回到http_handle

    else if (hm.message.len <= io->len) { //正确时走这里
      /* Whole HTTP message is fully buffered, call event handler */ //完全传送了调用事务处理

     nc->handler(nc, nc->listener ? MG_EV_HTTP_REQUEST : MG_EV_HTTP_REPLY,
                  &hm);  //调用了用户指定函数,分别是处理请求和做应答

   用户设置的回调函数调用 mg_serve_http

              [ 

                 1、  uri_to_path(hm, path, sizeof(path), &opts); //16进制字符码解码,uri重写(?)

                        [

                                *host_hdr = mg_get_http_header(hm, "Host");mg_get_http_header(hm, "Host");//寻找host键值对,返回值为键值对地址,给host_hdr

                                mg_url_decode(hm->uri.p, hm->uri.len, uri, sizeof(uri), 0);//16进制代替的字符解码(这函数名起的不好,糊涂) .p指在当前值起始位置

                                

                        ]

                2、指定了默认参数

                 3、mg_send_http_file 根据收到的http头内容分析,主要是对请求路径提取,对客户端进行反馈

                     [

                             static int is_dav_request(const struct mg_str *s) :寻找 "PUT","DELETE","MKCOL","PROPFIND"等特殊用法

                             S_ISDIR(st.st_mode)  ==#define S_ISDIR(x) ((x) &_S_IFDIR)  将st.st_mode与_S_IFDIR按位与,判定路径是目录还是文件

                             send_http_error(nc, 501, NULL);发送错误501 // 501错误:Web 服务器不理解或不支持客户端发送给它的 HTTP 数据流中找到的 HTTP 方法。

                            is_authorized:

                           mg_stat(path, &st):查找路径是否存在

                           !find_index_file(path, path_buf_len, opts->index_files, &st)) { //找寻路径下默认文件名,如index.htm存在,把文件信息存在st指向的缓存中,返回是否找到,找到返回1.否则返回0

                        

                     (注明一下opt选项

                            //s_http_server_opts.document_root = ".";  // Serve current directory  
                           //s_http_server_opts.enable_directory_listing = "yes"; 

                             //opts.per_directory_auth_file = ".htpasswd";

                             //opts.enable_directory_listing = "yes";

                           //opts.cgi_file_pattern = "**.cgi$|**.php$";

                           // opts.ssi_pattern = "**.shtml$|**.shtm$";

                           //opts.index_files = "index.html,index.htm,index.shtml,index.cgi,index.php";

                     )

                     mg_send_http_file2:重点处理了带range参数的请求包头,根据range情况计算应答文件长度,生成应答包头,并调用

                      transfer_file_data();

                            [

                                 transfer_file_data()组合数据,发送应答包。

                            ]

                          mg_printf(重要的函数)len = mg_vprintf(conn, fmt, ap);//把ap中的数据存入conn->send_mbuf中

                      ]

             ]

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是使用Mongoose服务器接收form-data图像数据,并解析图像数据,并使用OpenCV显示图像的示例代码: ```c++ #include <iostream> #include <fstream> #include <string> #include <cstring> #include <opencv2/opencv.hpp> #include "mongoose.h" #include "multipart_parser.h" static const char* s_http_port = "8000"; static struct mg_serve_http_opts s_http_server_opts; static std::string s_image_data; class MyParser : public multipart_parser { public: MyParser() : multipart_parser(), is_file_(false) {} void on_part_data(const char* data, size_t size) override { if (is_file_) { out_file_.write(data, size); } else { part_data_.append(data, size); } } void on_part_begin(const char* header, size_t header_size) override { part_data_.clear(); is_file_ = false; std::string header_str(header, header_size); if (header_str.find("filename=") != std::string::npos) { is_file_ = true; std::string filename = get_filename(header_str); out_file_.open(filename, std::ios::binary); } } void on_part_end() override { if (is_file_) { out_file_.close(); } else { s_image_data = part_data_; } } private: bool is_file_; std::string part_data_; std::ofstream out_file_; std::string get_filename(const std::string& header_str) { size_t pos = header_str.find("filename=") + strlen("filename="); std::string filename = header_str.substr(pos); if (filename.front() == '"' && filename.back() == '"') { filename = filename.substr(1, filename.size() - 2); } return filename; } }; static void handle_form_data(struct mg_connection* c, struct http_message* hm) { MyParser parser; parser.set_boundary("boundary"); parser.parse(hm->body.p, hm->body.len); mg_send_http_ok(c, "image/jpeg", s_image_data.size()); mg_send(c, s_image_data.c_str(), s_image_data.size(), MG_SEND_HTTP_BODY); } static void ev_handler(struct mg_connection* c, int ev, void* p) { if (ev == MG_EV_HTTP_REQUEST) { struct http_message* hm = (struct http_message*)p; if (mg_vcmp(&hm->method, "POST") == 0 && mg_vcmp(&hm->uri, "/upload") == 0) { handle_form_data(c, hm); } else { mg_serve_http(c, hm, s_http_server_opts); } } } int main() { struct mg_mgr mgr; struct mg_connection* nc; mg_mgr_init(&mgr, NULL); nc = mg_bind(&mgr, s_http_port, ev_handler); if (!nc) { std::cout << "Failed to create listener" << std::endl; return 1; } mg_set_protocol_http_websocket(nc); s_http_server_opts.document_root = "."; s_http_server_opts.enable_directory_listing = "no"; while (true) { mg_mgr_poll(&mgr, 1000); } mg_mgr_free(&mgr); return 0; } ``` 其中,`MyParser`类用于解析form-data数据,`on_part_begin`、`on_part_data`和`on_part_end`函数分别用于处理form-data的每个部分的开始、数据和结束,通过`is_file_`来判断当前部分是文件还是普通数据,`get_filename`函数用于从头部信息中解析出文件名。在`handle_form_data`函数中,调用`MyParser`类解析图像数据,将解析出来的数据保存到`s_image_data`中,然后使用`mg_send_http_ok`函数设置HTTP响应头,使用`mg_send`函数发送图像数据。在`ev_handler`函数中,判断请求方法和URI是否为upload,如果是,则调用`handle_form_data`函数处理请求,否则调用`mg_serve_http`函数处理静态文件请求。最后,使用Mongoose服务器监听端口并等待请求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值