网络编程——解剖HTTP之关于最常用的网络通信HTTP协议你应该知道的一些常识

引言

在当今互联网爆发的大时代,无论是Web程序还是App抑或是各种云服务等等要想发挥自身的价值都离不开网络,而理解程序之间通信的基本协议对于我们开发者来说相当重要,也是进阶的必经之路,这篇文章就好好总结下我们最熟悉的HTTP协议。

一、HTTP概述

1、HTTP的发展历程

HTTP(HyperText Transfer Protocal)超文本协议,用于定义万维网上各种超链接之间的通信规则,HTTP本身是无连接的,但是内部使用的是面向连接的TCP保证了数据的可靠传输,它的发展也是经历了几个历程,目前主流的还是HTTP/1.1。
在这里插入图片描述

2、HTTP协议的主要特性

  • 支持C/S(客户端/服务器)模式——HTTP协议由两部分程序实现,一个客户端和一个服务器程序,通过交互HTTP报文进行通信
  • 简捷快速——客户端向服务器发起请求的时候,只需要传递请求方法和路径即可,
  • 灵活——HTTP允许传输任意类型的数据对象,简单数据如纯文本、字符串等,复杂如二进制、流等等,只需要设置正确的Content-Type标示。
  • 无连接——即限制每次连接只处理一个HTTP请求,当服务器处理客户的请求并接收到客户的响应之后,立即断开连接,以节省传输时间。
  • 无状态——因为HTTP服务器并不保存关于客户机的任何信息,即无状态协议。

3、HTTP的基本运作方式

HTTP运作是以事务为原子单位的,所谓事务即一个HTTP事务由一条HTTP请求(由客户端发往服务端)和一条响应(服务器接收到来自客户端的请求响应处理并发回给客户端),与数据库中的事务的概念类似,只有两条操作都完成之后才算成功。
这里写图片描述

4、HTTP 请求解析流程概述

  • 首先经过DNS 协议映射到对应的IP地址
  • 再经过TCP协议分割,并按照序列号可靠发出
  • 借助IP协议,,通过路由器得到对应的接收IP地址
  • 然后经过TCP协议接收分割后得到的报文段并重组
  • 最终经过HTTP协议,返回服务器处理报文后的资源。

二、URI和URL

URI(Uniform Resource Identifiers),全称统一资源标识符,用于标志分布在整个因特网上的万维网文档,而URL(Uniform Resource Locator)统一资源定位符,

1、HTTP URI格式

形如:“http:” “//” hostname [ “:” port] [ biz_path ["?" query_params]]

  • hostname:主机域名(主机Ip地址),必填
  • port:端口号,非必须,若不填默认为80
  • biz_path:业务路径,非必须
  • query_params:查询串,GET请求的时候直接附在上面的参数,形如?user=cmo&pwd=crazy

2、HTTP URI 匹配原则

一般情况下在进行URI匹配时候必须按照大小写敏感的规范逐一字节进行对比,但以下情况除外:

  • 端口号为空或未给出的默认为80
  • hostname 不区分大小写
  • 协议名需要区分大小写,即http与HTTP不同,不过在有些浏览器会自动转成小写的
  • biz_path为空相当于"/"
  • 不属于保留或者不安全的字符相当于"%HEX HEX"格式的编码

3、 使用HTTP URI访问的基础流程

这里写图片描述
我们的浏览器给Web服务器发送了一个Request, Web服务器接到Request后进行处理,生成相应的Response,然后发送给浏览器, 浏览器解析Response中的HTML,这样我们就看到了网页
假设以浏览器访问http://www.crazy.com/index.html为例,经历以下步骤:

  • 浏览器器解析URI,确认是有效的URI
  • 向DNS服务器发起解析hostname——http://www.crazy.com的IP地址,再解析出端口号
  • 紧接着DNS服务器返回IP,假设为8.8.8.8
  • 接着浏览器与服务器(8.8.8.8)建立TCP连接
  • 然后浏览器发起获取文件的请求报文: GET /index.html Host: www.crazy.com
  • 服务器接受请求并给出响应报文
  • 最后释放掉TCP连接,浏览器显示文档

4、URL的基本语法

形如: schemal " : //" “internet adress” [:port] “/resource_file_name

  • schemal:表面访问资源所采用的协议,比如http、ftp、smtp等。
  • internet adress:服务器的因特网地址
  • port:端口号,默认为80
  • resource_file_name:完整的资源名带完整路径

几乎所有的URI都是URL。

5、连接和端口号

HTTP是个应用层协议,无需操心网络通信的具体细节,具体工作实际上是由底层的TCP/IP协议完成通信的,HTTP报文是通过TCP协议连接从一个地方传输到另一个地方去的。而在HTTP客户端向服务端发送报文之前,需要使用网际协议IP地址和端口号在两者之间建立一条TCP/IP连接,而TCP连接中,必须要知道对应的IP地址以及服务器上运行特定软件相关的TCP端口号

6、HTTP/1.1持久连接

HTTP/1.1逐渐停止了对keep-alive连接的支持,取代的是一种名为持久连接(persistent-connection),达到的效果是一样的,但机制更优些。与HTTP/1.0的keep-alive连接不同,HTTP/1.1持久连接默认是激活的,除非特别指明。否则HTTP/1.1假定所有连接都是持久的,要在事务处理结束之后将连接关闭,HTTP/1.1应用程序必须向报文中显示添加上一个Connection:close首部字段,否则HTTP/1.1客户端在收到响应之后,连接依然维持在打开状态,但是客户端和服务器是可以随时关闭空闲的连接的,而且不发送Connection:close也并不是意味值服务器永远将连接保持在打开状态。
这里写图片描述

三、媒体资源类型MIME

由于因特网上有很多种不同类型的数据、资源,HTTP为了区分正确处理不同的传输对象,因此需要标记传输对象的类型,即MIME(Multipurpose Internet Mail Extension,多用途因特网邮件扩展) ,最初MIME是用于在邮件系统中表示不同类型的邮件的,HTTP借鉴并用来标记多媒体类型,在开发中比较常见的MIME类型

MIME文档
text/htmlHTML格式的文本文档
text/plain普通的ASCII文本文档
image/jpgJPEG版本的图片
image/gifGIF格式的图片
video/quicktimeApple的QuickTime视频
application/vnd.ms-powerpointPPT格式的文档

四、HTTP请求命令

请求命令又可以叫做方法,每条HTTP报文都会包含一个方法,这些方法的将会协助服务器针对不同的方法进行不同的处理,比如说说获取一个Web页面、运行一个网管程序、删除一个文件等等,常见的有以下5种:

方法说明
GET从服务器向客户端发送命名资源
POST将客户端数据发送到一个服务器网关应用程序
PUT将来自客户端的数据存储到一个命名的服务器资源中去
HEAD仅发送命名资源响应中的HTTP报文的首部
DELETE从服务器中删除命名资源

五、状态码

HTTP/1.1中定义了5类状态码, 状态码由三位数字组成,第一个数字定义了响应的类别

  • 1XX ——提示信息 - 表示请求已被成功接收,继续处理

  • 2XX—— 成功 - 表示请求已被成功接收,理解,接受

  • 3XX —— 重定向 - 要完成请求必须进行更进一步的处理

  • 4XX —— 客户端错误 - 请求有语法错误或请求无法实现

  • 5XX —— 服务器端错误 - 服务器未能实现合法的请求
    在这里插入图片描述

六、HTTP报文

HTTP是通过报文来传输数据的,因而HTTP请求从一定程度上来说是不安全的,而HTTP报文本质上是一行行的简单文本格式的字符串构成的格式化文本,每一行都以两个字符——\r回车符(ASCII码13)和\n换行符(ASCII码 10)来组成的行终止标记序列CRLF
在这里插入图片描述
通常按照HTTP报文的类别又可以分为两种类型:请求报文和响应报文,不过两种报文基本机构大同小异都包含三大部分:起始行首部主体
在这里插入图片描述

1、起始行

起始行即报文的第一行,按照不同类别功能不一样:

1.1、请求行

在请求报文中请求行使用形如:< method > < request-url > < http-version > 格式用于说明这个请求要做些什么。

1.2、响应行

在响应报文中则是使用形如:< http version > < status-code > < respon-phrase > 用于表示服务器对请求的响应状态及结果。

2、首(头)部

首(头)部是用于标示主体数据的主机、类型、长度等信息的键值对, 起始行后面可以有一个或者多个首部字段(必须包含Host:xx),每个字段包含一个键和一个值,键值之间用冒号(:)来分隔连接(冒号之后是可以有一个空格),首部以一个空行CRLF结束,当然首部也可以分为多行来描述,但多出来的每行前面必须要有一个空格或者TAB符
在这里插入图片描述

3、主体

首部下的空行之后就是报文主体,在请求报文中则包含了所有要发给服务器的各种类型的数据;而在响应报文中则是装载了要返回给客户端的数据。总之,报文的主体就是一个由任意数据组成的数据块,但并不是所有的报文都包含实体的主体部分,有些报文也可以单纯以一个CRLF结束。值得注意的是,起始行和首部都是纯文本形式且结构化的,而主体则可以包含任意的数据——纯文本和二进制数据(比如图片、视频、音轨、软件程序等等),最后与起始行和首部都不同,主体也还可以为空,一般来说Get的请求报文的主体可以为空,而Post请求则会把参数以类似请求头的K-V形式存在请求报文的主体中。

最后请看下以下实例的报文图:
在这里插入图片描述
VS
在这里插入图片描述
当在解析请求的时候可能没有Content-Length而是遇见的Transfer-Encoding响应头,主要有编码方式:

  • Transfer-Encoding: chunked——数据以一系列分块的形式进行发送。 Content-Length 首部在这种情况下不被发送。。在每一个分块的开头需要添加当前分块的长度,以十六进制的形式表示,后面紧跟着 ‘\r\n’ ,之后是分块本身,后面也是’\r\n’ 。终止块是一个常规的分块,不同之处在于其长度为0。终止块后面是一个挂载(trailer),由一系列(或者为空)的实体消息首部构成。
  • Transfer-Encoding: compress——采用 Lempel-Ziv-Welch (LZW) 压缩算法。这个名称来自UNIX系统的 compress 程序,该程序实现了前述算法。
    与其同名程序已经在大部分UNIX发行版中消失一样,这种内容编码方式已经被大部分浏览器弃用,部分因为专利问题(这项专利在2003年到期)。
  • Transfer-Encoding: deflate——采用 zlib 结构 (在 RFC 1950 中规定),和 deflate 压缩算法(在 RFC 1951 中规定)。
  • Transfer-Encoding: gzip——表示采用 Lempel-Ziv coding (LZ77) 压缩算法,以及32位CRC校验的编码方式。这个编码方式最初由 UNIX 平台上的 gzip 程序采用。处于兼容性的考虑, HTTP/1.1 标准提议支持这种编码方式的服务器应该识别作为别名的 x-gzip 指令。
  • Transfer-Encoding: identity——用于指代自身(例如:未经过压缩和修改)。除非特别指明,这个标记始终可以被接受。

七、服务器解析HTTP请求的基本流程

一般情况下,无论是小型服务器还是大型先进的商用服务器的业务流程都差不多:建立连接——>接收请求——>处理请求——>访问资源——>构造响应——>发送响应——>记录事务处理过程

1、建立连接

如果客户端已经打开了一条道服务器的持久连接,可以使用那条连接来发送它的请求,否则客户端需要打开一条新的到服务器的连接。当客户端发起一条到服务器的TCP连接时,服务器就会建立连接,并判断连接的另一端是哪个客户端,从TCP连接中将IP地址解析出来,一旦新连接建立起来并被接受,服务器就会自动将新连接添加到服务器连接列表中。

2、接受请求并解析HTTP报文

连接上有数据到达时,服务器会从网络连接中读取数据,并将请求报文的内容解析出来。在解析请求报文的时候,服务器还会不定期地从网络上接收输入数据。

  • 首先解析请求行,查找请求方法、指定的资源标识符(URL)以及版本号,各项之间由一个空格分隔,并以一个回车换行(CRLF)序列作为行的结束标志。
  • 接着读取以CRLF结尾的报文首部
  • 再接着检测到以CRLF结尾的、标志首部结束,主体开始的空行。
  • 再解析长度(如果设置了Content-Length),读取请求主体。
    这里写图片描述

3、访问报文中指定的资源

4、构建并发送响应

一旦服务器识别出来资源,就会执行请求方法中对应的动作并响应报文,一般报文中包含有响应状态码、响应首部,响应主体。值得注意的是服务器并不是每次都一定会返回成功的报文,有时候也会返回重定向响应(由响应码3xx表示),重定向响应可以使得度武器将浏览器重定向到其他地方执行请求。

PS:下一篇使用原始Sockect 发送Http请求。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CrazyMo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值