使用HTTP协议浏览网页的原理

HTTP(Hypertext Transfer Protocol)超文本传输协议,是互联网数据传输的基础,目前广泛使用的是http/1.1版本。
HTTP是一种请求-响应式的协议,运行在应用层。应用层是TCP/IP模型中的一个层级,为了更好的理解HTTP协议,我们先来了解一下TCP/IP模型。

TCP/IP模型

互联网协议簇(Internet Protocol Suite)也就是TCP/IP协议是目前互联网通信的架构,包括5个层次,由高到低分别是应用层、传输层、网络层、数据链路层、物理层(Application Layer Transport Layer Network Layer Data Link Layer Physical Layer)(参考TCP/IP五层协议)。

从上图中可以看到,每层的功能和使用场景都不同。

  • 应用层是应用程序之间交换数据的层级,可以在同一个主机上,也可以在不同的主机之间,运行在此层的协议最常见的就是HTTP;在此层工作的是应用程序
  • 传输层运行在主机与主机之间,作用是为应用层建立一个通信的通道,TCP、UDP协议就是运行在此层;在此层工作的是4层交换机
  • 网络层负责生成和传输我们平时所说的IP数据报(datagram),网络层奠基了互联网,定义了寻址和路由,即通过IP地址将数据报传给下一个主机或路由器;在此层工作的是3层交换机、路由器
  • 数据链路层是基于MAC地址寻址的,运行在交换机组成的局域网中;在此层工作的是2层交换机
  • 物理层就是网线,集线器,中继器,负责编码、解码并传输电信号的

每一层都会对数据进行包装,数据在这些层上一步步传输就完成了互联网的通信,下图清晰的展示了这一过程

可以看到当使用TCP/IP传输数据时,发送端主机将数据一层一层的打包,然后通过网线等传递出去,接收端主机将获得的数据一层一层解包得到最终应用程序能够理解的数据。

graph TB
应用程序产生数据Msg -->传输层给Msg加上TCP或UDP头形成数据段或数据报
传输层给Msg加上TCP或UDP头形成数据段或数据报 --> 网络层给加上IP头形成数据包
网络层给加上IP头形成数据包-->数据链路层给加数据包上MAC头形成数据帧
数据链路层给加数据包上MAC头形成数据帧-->物理层将数据帧编码为电信号传播出去
物理层将得到的电信号解码为数据帧-->数据链路层将数据帧解包为数据包
数据链路层将数据帧解包为数据包-->网络层将数据包解包为数据段或数据报
网络层将数据包解包为数据段或数据报-->传输层将数据段或数据报解包为Msg
传输层将数据段或数据报解包为Msg-->应用程序读取Msg

HTTP协议

HTTP与TCP

在软件开发和使用中,我们经常听到“使用TCP连接方式”,“使用HTTP连接”等。其中的HTTP与TCP的关系对于初学者来说比较容易混淆。通过了解上面的TCP/IP模型,就更能很好的理清HTTP与TCP的关系了。HTTP与TCP是工作在不同层级的协议,应用层的HTTP定义了一种数据请求方式,数据的传输通道是由传输层的TCP建立的。即是,HTTP协议规定了A主机的浏览器软件与B服务器的软件之间的沟通的数据格式,TCP协议负责在A主机与B服务器之间建立数据传输通道。

graph LR
 id1[A TCP]--HTTP data-->id2[B TCP]

TCP建立连接的过程就是我们所熟知的三次握手,终端连接四次握手

sequenceDiagram
Client->>Server: SYN
Server->>Client: SYN-ACK
Client->>Server: ACK

ClientF->>ServerF: FIN
ServerF->>ClientF: ACK
ServerF->>ClientF: FIN
ClientF->>ServerF: ACK

其中,SYN:Synchronize Sequence Numbers ;ACK:acknowledgement

HTTP数据格式

HTTP协议是超文本即网页传输协议,是专门用来访问网站的。与之对比的同在应用层的FTP是文件传输协议,是用来与服务器之间传输文件的。两者都需要TCP为它们建立传输通道。既然HTTP规定了浏览器与网站服务器之间通信的数据格式,那我们就来看一看。HTTP是一种请求-响应式协议(Request–Response),请求信息格式与响应信息格式基本相同,都是由4部分组成,都是以文本(ASCII)的形式发送。

graph TB
id1[请求行]---id2[请求信息头]
id2[请求信息头]---id3[空白行]
id3[空白行]---id4[请求正文]

id11[状态行]---id12[响应信息头]
id12[响应信息头]---id13[空白行]
id13[空白行]---id14[响应正文]

(上图中,左边为请求数据格式,右边为响应数据格式)

  • 请求行,包括:请求方式(GET、POST),请求URL,协议版本号。用空格开,结尾加回车换行符<CR><LF>。例如GET /index.html HTTP/1.0
  • 请求信息头,包含User-Agent、Host等信息,参考HTTP头信息列表,同样每一项结尾以回车换行符<CR><LF>结束
  • 空白行,只能包含回车换行符<CR><LF>,没有空格
  • 请求正文,包含用POST方式传递的数据

http请求数据实际就是一段文本,第一行为请求行,第二行与空白行之间是信息头,空白行之后是用户发送的数据。

类似的响应数据

  • 状态行,包含协议版本号,状态码,状态消息,例如 HTTP/1.1 200 OK,以<CR><LF>结尾
  • 响应消息头,包含Content-Type等,以<CR><LF>结尾
  • 空白行,只能包含回车换行符<CR><LF>,没有空格
  • 响应正文,即返回的html网页,可以不必以<CR><LF>结尾,跟随操作系统可以是<LF><CR>

下面通过一个实验看看是不是按照这种方式来传输数据。

首先架设了PHP服务器,并用内置的server服务启动一个网站,index.php为

1
2
3
4
5
6
<?php
echo "your input is: ";
print_r($_GET);
if("admin"==$_GET[key])
{echo "admin";}
?>

然后在index.php文件夹启动服务

1
php -S 0.0.0.0:8000

正常启动后如图

使用浏览器访问网页

然后使用Fiddler工具对8000端口进行监听,准捕获数据。为了直观的显示POST和GET方式的区别,我写了一个网页文件,使用提交表单的方式访问php服务器。

1
2
3
4
5
6
7
8
9
10
11
12
<form name="input" action="http://192.168.1.50:8000/index.php" method="POST">
name: <input type="text" name="name"><br>
key: <input type="text" name="key">
<input type="submit" value="POST">
</form>


<form name="input" action="http://192.168.1.50:8000/index.php" method="GET">
name: <input type="text" name="name"><br>
key: <input type="text" name="key">
<input type="submit" value="GET">
</form>

网页效果

在文本框输入内容后,分别点击两个按钮,Fiddler监听的结果为

  • POST
  • GET

从Fiddle监听的结果可以看到浏览器发送和接受的数据与HTTP协议描述的一致。

总结

总结一下就是,当你输入一个网址回车后,浏览器会在你的电脑和网站服务器之间建立一条TCP通道,然后浏览器根据HTTP协议的规定将你的请求格式化为一段文本,在这条TCP通道上传递给服务器。服务器随之做出响应,也按照HTTP协议的规定返回给浏览器一段文本。如果返回的状态码为200,浏览器就会将服务器返回的文本的空白行之后的内容渲染成网页,这样你就看到了一张张精彩的网页了。

值得注意的是,使用GET方式请求,浏览器会将你的表单信息直接显示在请求行的url里,也就是会显示在浏览器的地址栏,缺乏隐私。POST方式会把表单信息作为请求正本包裹在http数据包中,在浏览器的地址栏式看不到的,起到一定的保密作用。

虽然很不要脸,但是还请您多多打赏 ^_^