【Linux】应用层协议:HTTP

URL

在之前的文章中我们实现了一个网络版本的计算器,在那个计算器中揉合了协议定制以及序列化反序列化的内容,我们当时也自己定制了一套协议标准,比如请求和响应的格式应该是什么?如何读到一个完整的报文?支持的运算符有什么?等等我们都有自己的标准。
那么有没有其他大佬针对应用层的某些使用场景,已经提前给我们写好了协议软件呢?有,这个协议就是HTTP协议,我们当时的协议仅仅是针对计算场景所设计的,而HTTP协议主要是针对web场景所设计的。
虽然到现在我们还没真正的接触HTTP协议的具体内容,但我们现在已经可以知道,HTTP中一定有网络套接字编程,序列化反序列化,以及HTTP要进行的自己的业务逻辑,而这三个方面实际和我们当时的计算器相同,都是分别对应OSI上三层模型,分别是会话,表示,应用,HTTP的业务逻辑一般主要是电子邮件的发送,远程登陆,文件传输等……

URL听着比较高级,但他其实就是我们平常所说的网址,红色下划线是域名,这个域名等价于IP,用于标识一台主机在全网中的唯一性,域名实际还会做解析,解析之后就是服务器的IP地址,用域名不用IP主要是因为域名用起来方便,域名会和特定的IP地址做映射,域名后面的就是访问资源的路径,/是web根目录,这个根目录可以是Linux下的任意一个目录,/后面的weixin_65660590是向服务器请求的资源,?后面的是请求资源时所匹配的参数。HTTPS是在HTTP的基础上增加了一层加密层,这个协议后面会讲。
在URL里面我们并没有看到port,这是怎么回事呢?其实是因为浏览器自动忽略了服务器的端口号,但真正在发送url进行请求的时候,还要将端口号填充到URL里面,那浏览器怎么知道自己要访问的服务器的端口号是多少呢?浏览器其实是通过我们的协议来知晓服务器的端口号的,一般HTTP协议对应服务器的端口号是80,HTTPS对应的服务器的端口号是443.
服务器端口号大部分情况下都可以省略,因为协议和端口号是强绑定的!所有的网络服务都有对应的明确的端口号,这些是已经确定好的。
在这里插入图片描述

而我们所有的网络行为无外乎就两种,一种是通过HTTP协议从服务器拿下来对应的资源,一种是通过HTTP协议向服务器上传你本地的资源。
你在网络中看到的音频,视频,网页,图片等等,都是服务器上的文件资源,客户端看到的这些资源实际就是服务器对应返回的响应结果,因为文件资源的种类很多,文件后缀就很多,但这些文件的传输HTTP协议都能搞定,比如音乐,视频等文件都能传输,所以HTTP叫做超文本传输协议,不仅仅只能传文本,还能传其他很多种类的文件资源。
像我们平常刷抖音,听网易云实际就是抖音的服务器将他内部的视频传输到我们客户端,或是网易云的服务器将音乐传输到我们的客户端,而我们远程登录,在浏览器中搜索某些东西等行为就是将信息提交到远端服务器,将账号密码或搜索的关键字提交给服务器。
在这里插入图片描述

在url中像// ? : @ #等字符已经被当作特殊意义处理了,所以如果你要搜索的内容中出现了这些特殊意义的字符,则他们会被编码化也就是urlencode化,除这些已经被使用的特殊字符外,汉字也会被urlencode化。
一般来说网页URL只能使用英文,数字,还有一些特定的字符等可以不经过编码直接用于URL,其他的字符都必须先经过urlencode编码才能用于URL,否则传给服务器的request URL会包含乱码,服务器无法正确识别URL,自然就无法确定你要访问什么样的资源,这样就会出现错误。


HTTP协议格式

HTTP请求和响应的格式

HTTP请求分为请求行,请求报头,空行,请求报文这4个部分,其中请求行又以空格作为分隔符,由请求方法 URL 协议版本三部分组成,HTTP这里最常用的两个请求方法就是GET和POST,后者可以保证用户数据的私密性,这个我们后面会讲,常用的协议版本是1.1,除1.1外还有1.0版本。
request的Header报头中是以行为单位的HTTP请求的各种属性,每行都是由name 冒号 空格 value \r\n组成,接下来是空行,空行之后就是正文内容body,请求正文可以为空,如果你只单纯的想从服务器上拿资源到本地的话,请求正文可以为空,如果你想向服务器上提交一些内容,比如提交账号和密码进行登录,又或是提交一些搜索时需要的关键字进行相关网络内容的搜索,这些信息就可以放在请求正文body中。

HTTP响应分为状态行,响应报头,空行,响应报文这四个部分,其中状态行又以协议版本,状态码,状态码描述组成,常见的状态码有200 404 502等等,响应报头的格式和请求报头一样,内容包含响应内容的各种属性,接下来是空行,之后就是响应正文,相应正文就是客户端请求的资源内容,所以响应正文内容可以是html网页,图片,视频,音频等各种资源。
在这里插入图片描述
HTTP协议也会遇到我们当时定制网络版本计算器协议时所遇到的问题,比如你怎么保证读到一个完整的请求或响应报文呢?
其实很简单,因为首行和报头都是以行作为分隔符的,所以只要while循环一直按行读取,直到读取到空行为止,这样就读取完了首行和报头,而报头中会有一个字段Content-Length表示正文内容的长度,则读取空行结束后,我们只需要再读取Content-Length长度个字节的内容即可读取一个完整的报文。

HTTP的请求和响应怎么做到序列化和反序列化呢?这个问题也很简单,HTTP并没有使用json protobuf xml等方案来实现序列化和反序列化,因为根本没那个必要!如果要进行序列化,则从第一行开始,将首行 报头 空行 正文等内容,以\r\n作为分隔将每行字符串进行拼接,拼接成一个大字符串,然后直接发送即可。反序列化则按照以\r\n作为分隔符,读取每个小字符串的内容即可。
所以HTTP的序列化和反序列化实际就是通过特殊字符\r\n来将每个内容分隔开来的。
如果正文的内容是图片 音频 视频等文件,则他的序列化和反序列化工作一般不考虑,直接按照二进制发送就行。

打印出http请求报文(了解一下request的各个字段)

下面是HTTP服务器的代码,服务器的代码和最开始我们写TCP套接字编程的代码没太大区别,首先服务器初始化时,要传递一个回调函数func,这个函数是HTTP的业务逻辑处理函数,并且服务器运行后,子线程执行的函数也发生了改变,我们让主线程负责会话管理,监听来自客户端的连接请求并受理,而孙子进程负责给客户端提供对应的HTTP服务,执行HttpHandler方法。
在HttpHandler里面,首先要保证读取一个完整的请求报文,但今天我们不做这个工作了,这个工作做起来比较麻烦,需要套一堆的while循环进行判断,我们大概率是直接能读取到一个完整的HTTP请求的。
所以直接从sockfd里面读取HTTP请求,将内容放到buffer里面

在这里插入图片描述
上面就是我们所写的HTTP服务器,那HTTP的客户端呢?我们没有写浏览器的客户端啊。其实不用担心,我们有现成的HTTP客户端,就是浏览器,我们可以用本主机的浏览器来发送HTTP请求到云服务器上,而我们在云服务器上写的代码完成的HTTP请求处理工作其实很简单,就是单纯的把HTTP请求内容打印出来而已。
所以在输入Web地址的一栏中,我们可以用ip+端口号的方式来访问我们的云服务器,只要一访问,vscode的命令行就会打印出HTTP请求的内容。内容包括首行 报头 空行 以及正文,当然今天我们仅仅只是访问了一下服务器,没有向服务器提交什么信息,所以请求正文自然为空,什么都没有。

在这里插入图片描述

浏览器请求时,默认的请求方法是GET,如果请求时请求资源的路径没有指定,则服务器会默认返回web server的首页,也就是web根目录下的index.html首页,通常情况下一个网站只有一个index.html作为此网站的首页,一个服务器可以存在多个网站,每个网站会分配不同的端口号。
HTTP在请求时,还会交换bs(browser server)通信双方的协议版本,因为客户端的版本可能由于未及时更新导致和服务器的协议版本不兼容,为了保证服务器返回的响应报文的协议版本和客户端保持一致,所以服务器需要知晓browser的协议版本。
通过HTTP请求的User-Agent字段,还可以理解一个生活现象,我们用电脑浏览器搜索微信进行下载时,浏览器会主动给我们推送pc版本的微信,用手机浏览器搜索微信进行下载时,浏览器会主动推送Android版本的微信,这是为什么呢?因为浏览器的服务器会收到HTTP请求,而HTTP请求的User-Agent字段包含了客户端的操作系统版本信息,通过OS版本信息,浏览器就可以给我们推荐响应版本的微信app了

硬编码响应一个html网页

上面仅仅只是打印了http请求的内容,下面我们构建http响应,让服务器给浏览器返回一个静态的html网页,再谈论html网页之前先来介绍一个本地测试的工具telnet,该工具可以远程登陆我们的服务器,进行TCP连接,连接成功后,可以在命令行中手动构建http请求,测试服务器返回的http响应结果是否正确。
安装telnet的指令分别为sudo yum install -y telnet-server和sudo yum install -y telnet.*
安装成功后,输入ctrl+],按下回车就可以得到telnet的命令行,得到命令行之后,继续按下回车,然后开始构建HTTP请求的请求行并按下回车,然后服务器就会返回该请求行对应的响应内容。

在这里插入图片描述

在这里插入图片描述

首页中增加跳转链接(重新发起http请求)

如果想要将一个HTML文件返回给浏览器实际也很简单,我们只需要以读取文件的方式,将HTML文件内容读取到响应正文respbody里面即可,然后将respbody字符串拼接到resp中的outbuffer字段里面即可,实际就是多了个文件操作。
而在首页中增加跳转链接也很简单,设置href加路径即可,当我们在首页中点击链接时,其实就是重新又向服务器发起该链接对应资源的请求,如果你点击a,则服务器会重新给你返回a网页的资源,重新在浏览器端显示出来。
在这里插入图片描述

2.2.5 首页中增加图片(服务器读取图片文件内容时,必须以二进制读取到缓冲区中)

除将HTML文件返回给浏览器外,我们也可以将图片文件返回给浏览器,两者本质是相同的,因为在Linux下一切皆文件!别跟我说你是音频 视频 网页 还是什么乱七八糟的东西,我linux服务器不管这些,我只认文件,无论是什么到linux这里全都是文件,所以无论返回给浏览器什么,其实无非都是把文件内容按照二进制的方式先读取到缓冲区中,然后调用socket接口将缓冲区的内容发送回浏览器而已,本质都是相通的。
在这里插入图片描述

所以用户看到的一个网页,可能是经过多个资源组合而成的!例如我们现在所看到的网页是由多个HTML文件组成,包括体育新闻,金融新闻,首页HTML文件,以及图片文件.jpg,每次发送HTTP请求时,请求资源的类型都不一样,那我们怎么知道请求的资源类型是什么呢?
其实道理很简单,答案就藏在请求资源的后缀里,我们可以从path路径内容中倒着查找,以.作为分隔符将后缀字符串切割出来,放到请求结构体req的suffix字段里面,然后我们就可以把这个字段转成Content-Type: text/html\r\n等这样的类型,根据切分出来的suffix字段进行穷举类型,是什么类型我们就将该类型尾插到Content-Type: 中,然后将此字段尾插到响应结构体resp中的outbuffer里面。


HTTP中细节探究

HTTP的请求方法(GET和POST)

HTTP的请求方法有很多,但我们只要了解两个最常用的就够了,一个是GET获取资源,一个是POST上传资源,GET方法通常用于请求服务器发送一些信息,GET方法的主要限制是URL的长度。大多数浏览器和服务器都对URL的长度有限制。
一般向服务器提交数据的时候,前端都是通过form表单的方式来提交,浏览器会自动将form表单中的内容转换为GET或POST方法下的http请求中的某个字段,下面是表单提交的路径和方法,一旦输入内容点击登录后,页面会自动跳转到/a/b/c.py目录.
在这里插入图片描述

GET方法比较尴尬,用户提交的信息直接拼接到url的后面了,谁都能够看到,私密性不够好。
而POST方法会将用户提交的参数信息保存到请求正文里面,然后提交给服务器,用户是看不到的,私密性比GET更好一些。
但值得注意的是GET和POST只是在私密性上有所不同,两者都是不安全的,网上某些人说POST方法比GET方法更安全,这种说法是错误的,想要使网络通信安全,则必须加密(HTTPS)。
一般如果不要求私密性,想要用URL给服务器传参,参数必须是简洁的KV式的参数,这样的场景可以使用GET方法。如果传参内容过长,则可以使用POST方法来传,因为请求正文可以很大,例如上传简历,文件什么的,都可以使用POST,也比GET方法更私密一些。

在这里插入图片描述

HTTP状态码

在这里插入图片描述
在中构建响应的时候,状态行中的状态码直接写的200,状态码描述是OK。那么状态码到底有哪些呢?它们代表的意义是什么?
在这里插入图片描述
重定向状态码(3XX):

这些状态码没啥好说的,重点说一下重定向。

重定向就是将网络请求重新定个方向转到其它位置(跳转网站),此时这个服务器相当于提供了一个引路的服务。
相信都有过这样的经历,打开一个网址以后,自动就弹出一些广告网页,这就是一种重定向。

浏览器发送请求给服务端,服务端返回一个新的url,并且状态码是3XX,浏览器会自动用这个新的url向新地址的服务端发起请求。
所以说,重定向是由客户端完成的,当客户端浏览器收到的响应中状态码是3XX后,它就会自动从响应中寻找返回的新的url并发起请求。

重定向又有两种:

永久重定向:状态码为301。
临时重定向:状态码为302和307。
临时重定向和永久重定向本质是影响客户端的标签,决定客户端是否需要更新目标地址。

如果某个网站是永久重定向,那么第一次访问该网站时由浏览器帮你进行重定向,但后续再访问该网站时就不需要浏览器再进行重定向了,此时直接访问的就是重定向后的网站。

而如果某个网站是临时重定向,那么每次访问该网站时都需要浏览器来帮我们完成重定向跳转到目标网站。
在这里插入图片描述

当浏览器发起请求访问index.html的时候,收到的响应中,状态码是307,所以浏览器不解释index.html,而是根据响应报头中的Location属性,得到新的url,再向新的url发起请求,得到新的响应


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

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

相关文章

【路径规划】基于六次多项式的多关节机器人避障路径规划

最近迷上了机械臂避障轨迹规划,因为之前一直做的都是无障碍物轨迹规划,所以这次想试一下有障碍物的,把避障算法用在我的SimMechanics机械臂上,看看效果咋样。以下定义不区分路径规划和轨迹规划。   by the way,本文实…

二叉树的定义和基本术语及性质

二叉树是一种特殊的树形数据结构,它对每个节点的子节点数进行了限制,即每个节点最多有两个子节点。这种结构使得二叉树成为了许多算法和数据结构的基础,如二叉搜索树、堆、哈夫曼编码等。本文将详细探讨二叉树的定义、基本术语和性质&#xf…

BGP扩展知识总结

一、BGP的宣告问题 在BGP协议中每台运行BGP的设备上,宣告本地直连路由在BGP协议中运行BGP协议的设备,来宣告通过IGP学习到的未运行BGP协议设备产生的路由;(常见) 在BGP协议中宣告本地路由表中路由条目时,将…

DNF手游攻略:2024新手攻略大全

在《DNF手游》的世界中,前期阶段对于新手玩家来说至关重要。以下是一份综合整理的新手攻略,帮助玩家快速适应游戏并取得进展。 1. 角色建立策略: 在前期,建议玩家建立3个角色,包括1个大号和2个小号。大号可以根据个人喜…

谷歌google浏览器无法更新Chrome至最新版本怎么办?浏览器Chrome无法更新至最新版本

打开谷歌google浏览器提示:无法更新Chrome,Chrome无法更新至最新版本,因此您未能获得最新的功能和安全修复程序。点击「重新安装Chrome」后无法访问此网站,造成谷歌浏览器每天提示却无法更新Chrome至最新版本。 谷歌google浏览器无…

SaaS知识库哪些比较好用?中小企业也能适用

在快节奏的商业世界中,拥有一个高效、易于使用的知识管理工具是提升工作效率的关键。对于中小企业来说,选择合适的SaaS(软件即服务)知识库平台尤为重要,因为它不仅能帮助员工快速找到信息,而且还能优化客户…

数据结构进阶之堆

今天我们学习的是数据结构里面的堆,大家先看看我们今天要学习的内容 一、堆概念及认识 在学习堆之前我们得先明白完全二叉树是什么样子,因为堆是依据完全二叉树的结构来实现的,所以在这里我先告诉大家完全二叉树的是什么,如下图…

Excel中输入数字会改变怎么办?

一、数字显示不全,以“#”号代替 随着列宽的缩小,数字逐渐被“#”号代替(首先数字的格式是“数值型,且只有整数”) 原因分析:单元格中的数字无法完全显示,Excel会自动用“#”号填充剩余的空间 解…

00_如何使用国内镜像源下载QT

如何使用国内镜像源下载QT 如何使用国内镜像源下载QT 如何使用国内镜像源下载QT 第一步:下载下载qt online installer 网站:https://download.qt.io/official_releases/online_installers/ 添加链接描述 下载windows版本 第二步: 剪切放…

搭建个人智能家居 4 -WS2812B-RGB灯

搭建个人智能家居 4 - WS2812B-RGB灯 前言说明ESPHomeHomeAssistant 前言 上一篇文章我们已经完成了第一个外设的添加(一个LED灯),今天接着来“壮大”这个系统,添加第二个外设“RGB灯”。 环境搭建可以回顾前面的文章。前文回顾&…

AutoCAD 2024 安装注册教程

前言 大家好,我是梁国庆。 本篇分享的安装包是 AutoCAD 的全新版本——AutoCAD 2024,下文安装教程中简称 AutoCAD。 时间:2024年4月8日。 获取 AutoCAD 安装包 我已将本篇所使用的安装包打包上传至百度云,扫描下方二维码关注…

Linux 内核学习(1) --- 时钟子系统

标题 时钟系统说明时钟树Clock Provider时钟通用数据结构clock_device 的注册clock_provider DTS配置和注册clock consumer时钟系统总结 时钟系统说明 时钟就是 SoC 中的脉搏,由它来控制各个部件按各自的节奏跳动。比如,CPU主频设置,串口的波…

windows本地运行dreamtalk踩坑总结

dreamtalk是一个语音图片转视频的一个工具,就是给一段语音加一个头像图片,然后生成一段头像跟语音对口型的视频,其实还是很有意思的,最近阿里发布了一个类似的模型,但是还没开源,从展示视频看,阿…

itext7 pdf转图片

https://github.com/thombrink/itext7.pdfimage 新建asp.net core8项目&#xff0c;安装itext7和system.drawing.common 引入itext.pdfimage核心代码 imageListener下有一段不安全的代码 unsafe{for (int y 0; y < image.Height; y){byte* ptrMask (byte*)bitsMask.Scan…

Centos 7.9.2009 下 Gitlab 完全卸载

一、linux版本&#xff1a;lsb_release -a 二、GtiLab 版本 # 查看gitlab的版本号 cat /opt/gitlab/embedded/service/gitlab-rails/VERSION 三、开始卸载 3.1&#xff0c;停止Gitlab 相关服务 # 停止所有GitLab相关服务&#xff1a; sudo gitlab-ctl stop# 移除GitLab包…

【2024年MathorCup数模竞赛】C题完整解析(代码与技术文档)

C题第一问 1 数据预处理2 问题一2.1基于混合ARIMA-LSTM预测模型的未来30天货量预测2.1.1 自适应混合ARIMA-LSTM混合预测模型的建立2.1.2 自适应混合ARIMA-LSTM混合预测模型的求解 2.2 基于混合ARIMA-LSTM预测模型与模糊修正的未来30天每小时货量预测 代码分享 目前已经完成C题数…

如何利用python机器学习解决空间模拟与时间预测问题

徐老师&#xff1a;副教授&#xff1a;长期从事定量遥感、遥感数据同化、地表水热通量转化等相关领域的研究&#xff0c;发表多篇相关领域核心期刊论文&#xff0c;具有丰富的实践技术经验。 专题一、机器学习原理与概述 了解机器学习的发展历史、计算原理、基本定义&#xf…

vue快速入门(二十一)计算属性

注释很详细&#xff0c;直接上代码 上一篇 新增内容 计算属性的基本应用 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.…

Springboot+Vue项目-基于Java+MySQL的社区团购系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

酷得智能 无人机方案开发

东莞市酷得智能科技有限公司&#xff0c;是一家专业的技术服务公司&#xff0c;致力于为各类智能硬件提供高效、稳定、安全的底层驱动解决方案。拥有一支经验丰富、技术精湛的团队&#xff0c;能够为客户提供全方位的底层驱动开发服务。 无人机功能介绍&#xff1a; 1、自动跟…