浏览器访问服务器的过程、HTTP协议、开发者工具、HTTP请求报文协议分析、HTTP响应报文协议分析、长连接和短连接、案例-模拟浏览器的功能实现
1.浏览器访问服务器的过程
目标
知道浏览器访问服务器的过程
知道URL的含义
知道域名和ip的关系
<1>浏览器请求的基本流程如下:
浏览器访问百度服务器程序的通信流程
在浏览器的地址栏输入网址(url)
当用户输入回车的时候,域名解析服务器会把域名解析成一个对应的ip地址
和百度服务器的web应用程序建立连接
发送http协议格式的请求数据
百度服务器的web应用程序会根据请求在本地获取请求的资源数据
百度服务器的web应用程序会发送http协议格式的响应数据
http: 默认使用端口号是80
https: 默认使用端口号443
http协议的工作模式: 请求+响应的模式,先有请求然后再有响应
图1 - mini-web服务器工作流程
1. 用户输入网址.
2. 浏览器请求DNS服务器, 获取域名对应的IP地址和端口号.
3. 请求连接该IP地址服务器.
4. 发送资源请求. (HTTP协议)
5. web服务器接收到请求, 并解析请求, 判断用户意图.
6. 获取用户想要的资源.
7. 将资源返回给web服务器程序.
8. web服务器程序将资源数据通过网络发送给浏览器.
9. 浏览器解析请求的数据并且完成网页数据的显示.
<2>网址是什么呢?
网址有称为URL,URL的英文全拼是(Uniform Resoure Locator),表达的意思是统一资源定位符,通俗理解就是网络资源地址。
URL的组成部分大概分为三部分:
协议头部分
域名部分
资源路径部分
比如: http://news.china.com.cn/2018-06/12/content_52060465.htm URL的格式为: http://: 协议部分 news.china.com.cn: 域名部分 /2018-06/12/content_52060465.htm:资源路径部分
<3>域名是什么呢?
我们在访问一台服务器的时候, 需要记住该服务器的IP地址, 由于IP地址不利于人们记忆, 所以推出的域名技术. 域名是由一串用点分隔的名字组成的 Internet 上某一台计算机或计算机组的名称, 用于在数据传输时标识计算机的位置.
域名可以用来表示一个单位、机构或可以利用个人在 Internet上 的确定的名称或位置. 域名是惟一的. 客户可以利用这个名字找寻有关的产品和服务信息.
<4>DNS 是什么呢?
由于我们用域名来标识计算机的位置, 但是我们前面讲过, 网络上标识主机的唯一标识是IP地址, 所以就需要记录一下, 一个域名和IP地址的对应关系, 这个对应关系就存储在DNS服务器中, 当我们向DNS发出请求时, DNS会返回给我们域名所对应的IP地址.
域名: 方便记忆某台电脑的主机地址,域名最终对应的是一个ip地址
DNS: 域名解析服务器, 当使用访问某个网址的时候,域名解析服务器会把域名解析成一个对应的ip地址
小结
浏览器访问服务器其实就是请求和响应的过程
URL通俗理解就是请求资源在网络中的地址
通过域名可以解析出来一个ip地址,域名是方便大家记忆某台主机地址的
2.HTTP协议
目标
知道http协议的作用
<1>HTTP协议简介
HTTP协议就是超文本传输协议(HyperText Transfer Protocol),通俗理解是浏览器和web服务器传输数据格式的协议,HTTP协议是一个应用层协议。
HTTP协议是基于TCP协议的,发送数据之前需要建立好连接
HTTP是万维网的数据通信的基础。设计HTTP最初的目的是为了提供一种发布和接收HTML页面<网页>的方法。
HTTP协议的制作者是蒂姆·伯纳斯-李,他供职于CERN(欧洲核子研究组织)
1991年发布的0.9版,该版本极其简单,只有一个GET请求方法
1996年5月,HTTP/1.0版本发布
1997年1月,HTTP/1.1版本发布,目前使用就是HTTP/1.1版本
<2>网络传输-TCP/IP四层模型
TCP/IP模型又称为TCP/IP协议族,是一系列网络协议的总称。TCP/IP模型一共包括几百种协议,制作协议的目的,就是保证计算机之间可以按照一定格式进行数据通信。
1. 网络接口层(数据链路层/网络接口层):包括操作系统中的设备驱动程序、计算机中对应的网络接口卡.
2. 网络层:处理分组在网络中的活动,比如分组的选路.
3. 传输层:主要为两台主机上的应用提供端到端的通信.
4. 应用层:负责处理特定的应用程序细节.
<3>HTTP协议的工作模式
HTTP协议的工作模式是一次请求(request)和一次响应(response)的模式
3.使用谷歌开发者工具查看HTTP协议的通信过程
目标
知道谷歌浏览器开发工具的使用流程
这里介绍 谷歌开发者工具使用
windows和Linux平台按F12调出开发者工具, MAC选择 视图 -> 开发者工具。
在 web 应用中, 服务器把网页传给浏览器, 实际就是把网页的 HTML 代码发送给浏览器, 浏览器解析显示出来. 而浏览器和服务器之间的传输应用层协议就是 HTTP. 所以:
HTML 是一种用来定义网页的文本, 会 HTML 就可以编写网页.
HTTP 是用来在网络上传输 HTML 文本的协议, 用于浏览器和服务器的通信.
Chrome 浏览器提供了一套完成的开发者工具, 很适合 web 开发者.
图4 - 打开开发者工具
图5 - 开发者工具界面
元素(Elements):用于查看或修改HTML元素的属性、CSS属性、监听事件、断点等.
控制台(Console):控制台一般用于执行一次性代码, 查看JavaScript对象, 查看调试日志信息或异常信息.
源代码(Sources):该页面用于查看页面的HTML文件源代码、JavaScript源代码、CSS源代码, 此外最重要的是可以调试JavaScript源代码, 可以给JS代码添加断点等.
网络(Network):网络页面主要用于查看 header 等与网络连接相关的信息.
注意:
Network 中的每一项就是一次请求/响应过程, 点击每一项, 可查看本次请求响应的报文信息.
4.HTTP 请求报文协议分析
目标
知道HTTP协议请求报文的格式
首先,我们通过开发者工具查看一下请求报文的格式.
Request Headers 中就是请求的报文数据内容. 下面就是我们要请求的报文示例数据:
GET / HTTP/1.1
Host: localhost:10000
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7
<1>GET / HTTP/1.1 叫做请求行. 里面包含3个信息, 以空格隔开,
第一个叫做请求方法, 除了 GET 方法之外, 还有 POST 方法, 除此之外还有其他方法, 这两种最常用. GET 主要用于从服务器获得数据, POST 主要用于从浏览器提交数据到服务器. 比如像百度首页提供的上传图片的功能, 就是用POST方式.
第二个表示请求的资源路径. 当请求的URL是 https://www.baidu.com/, 那么我们会发现 路径会显示 '/', 那么如果请求的URL是 https://www.baidu.com/index.html, 我们会发现路径显示是 '/index.html'.
第三个表示 HTTP 协议的版本, 那么既然有 1.1版本, 前置版本肯定是1.0了,那么两个版本有什么区别呢? 1.1版本比1.0的版本主要多个一些请求方法等扩充协议的内容.
<2>请求头. 除了第一行之外, 剩下的所有数据的格式都是类似的.
Host 表示浏览器要请求的主机地址. 这服务器ip地址,如果端口号不显示,默认使用:80
Connection 表示浏览器和服务器之间的连接方式, 浏览器和服务器连接是长连接( keep-alive)还是短连接
Cache-Control: 缓存方式 max-age=0表示不缓存
User-Agent 用户代理, 客户端应用程序的类型, 指定User-Agent可以做到初步反爬 。我们使用谷歌浏览器和火狐浏览器分别请求百度, 那么会发现 User-Agent 的值是不一样的, 它主要是用于浏览器告诉服务器自己的身份, 比如浏览器端使用的操作系统是什么版本, 浏览器是什么版本等等. 服务器端为什么需要知道这个信息呢? 我们后面会讲到爬虫,爬虫程序主要是从服务器端获取数据, 那么服务器端就会有反爬机制, 服务器不希望爬虫来获取数据, 所以通过该项可以知道客户端是否是爬虫程序. 如果爬虫程序想伪装成一个浏览器的请求, 就必须设置此项.
Accept 表示浏览器告诉服务器, 自己能够接收并识别的文件类型.
Accept-Encoding 表示浏览器能够处理的压缩方式. 为什么需要压缩呢? 当网页数据量大的时候, 压缩之后可以提高传输速率, 提高用户体验.
Accept-Language 浏览器可以接收的文本语言, 如果非中文编码可能会出现乱码.
Cookie: 客户端用户身份的一个表示
小结
注意:
form data:请求体(客户端给服务器发送的数据),HTTP请求报文可以分为GET请求和POST请求报文,要注意的是GET请求没有请求体,POST请求有请求体信息
5.获取请求报文原数据
目标
知道浏览器使用的是http协议并能发送请求报文数据
需求
使用python语言写一个tcp服务端程序,让浏览器访问自己的服务端程序,获取浏览器的请求报文数据
参考代码
# tcp服务端的程序
import socket
# 判断是否是程序的入口
if __name__ == '__main__':
# 创建tcp服务端socket
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定端口号
tcp_server_socket.bind(("", 8080))
# 设置监听
tcp_server_socket.listen(128)
# 等待接收客户端连接请求
service_client_socket, ip_port = tcp_server_socket.accept()
# 接收浏览器请求的原始报文数据
recv_data = service_client_socket.recv(4096)
print(recv_data)
service_client_socket.close()
tcp_server_socket.close()
小结
http原始请求报文数据请求行、请求头之间会有\r\n特殊数据
6.HTTP 响应报文协议分析
如何使用开发者工具查看请求报文, 以请求 Baidu.com 为例:
HTTP/1.1 200 OK
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html; charset=utf-8
Date: Wed, 14 Mar 2018 09:52:48 GMT
Server: BWS/1.1
<1>第一行 HTTP/1.1 200 OK 叫做响应行,
共分成3部分, 第一部分 HTTP/1.1 表示 HTTP协议的版本, 第二部分是一个数字, 这个数字表示响应状态码, 用户向服务器发出了请求, 如果服务器正常返回响应报文, 那么状态码一般都是200, 第三部分的 "OK" 表示原因短语, 表示对前面状态码的简单描述. 这里需要说的是, 响应的状态码除了 200 之外, 还有其他的状态码, 下面是常见的状态码:
■ 302 redirect, 我们通过 302 状态码可以指示浏览器跳转到某一个 URL.
404 NOT FOUND, 当我们访问一个不存在的 URL 时, 一般会返回404状态码, 告诉浏览器, 你访问的 URL 是不存在的.
500 Internal Server Error, 服务器遇到了一个未曾预料的状况, 导致了它无法完成对请求的处理. 一般来说, 这个问题都会在服务器端的源代码出现错误时出现.
<2>响应头
Server: nginx/1.10.2 服务器的名称
Date: Thu, 06 Sep 2018 04:11:11 GMT 服务器的时间: 格林威治时间, 相当于0时区
Content-Type: text/html;charset=UTF-8 服务器告诉客户端浏览器响应内容的文本格式及编码格式
Transfer-Encoding: chunked 表示服务器发送给客户端的数据大小不确定,如果发送数据完成会有一个特殊的标识数据\0\r\n , Content-Length: 100 明确告诉客户端发送数据的长度, 两者会有其一
Connection: keep-alive 表示连接状态, keep-alive表示长连接
X-Application-Context:application:production:6202 服务器程序程序员自己设置的响应头信息
Content-Language:zh-CN 服务器告诉客户端支持的语言类型
<3>空行(\r\n)
<4>响应体(查看响应体数据选择response选项卡)
小结
HTTP协议响应报文分为4部分,每部分之间使用\r\n进行分割
响应行
响应头
空行(\r\n)
响应体
7.长连接和短连接
目标
知道长连接和短连接的特点
在HTTP/1.0中, 默认使用的是短连接.也就是说, 浏览器和服务器每进行一次HTTP操作, 就建立一次连接, 但任务结束就中断连接.如果客户端浏览器访问的某个HTML或其他类型的 Web 页中包含有其他的Web资源,如js文件、图像文件、CSS文件等;当浏览器每遇到这样一个Web资源,就会建立一个HTTP会话。
但从 HTTP/1.1起,默认使用长连接,用以保持连接特性。使用长连接的HTTP协议,会在响应头有加入这行代码:
长连接 Connection:keep-alive
短连接 Connection:close
在真正的读写操作之前,server与client之间必须建立一个连接,
当读写操作完成后,双方不再需要这个连接时它们可以释放这个连接,
连接的建立通过三次握手,释放则需要四次握手,
所以说每个连接的建立都是需要资源消耗和时间消耗的。
<1>TCP短连接
模拟一种TCP短连接的情况:
client 向 server 发起连接请求
server 接到请求,双方建立连接
client 向 server 发送消息
server 回应 client
一次读写完成,此时双方任何一个都可以发起 close 操作
一般都是 client 先发起 close 操作。当然也不排除有特殊的情况。
从上面的描述看,短连接一般只会在 client/server 间传递一次读写操作!
<2>TCP长连接通信过程
client 向 server 发起连接
server 接到请求,双方建立连接
client 向 server 发送消息
server 回应 client
一次读写完成,连接不关闭
后续读写操作...
长时间不操作之后client发起关闭请求
<3>TCP长/短连接的优点和缺点
长连接可以省去较多的TCP建立和关闭的操作,节约时间。但是如果用户量太大容易造成服务器负载过高最终导致服务不可用
短连接对于服务器来说实现起来较为简单,存在的连接都是有用的连接,不需要额外的控制手段。但是如果用户访问量很大, 往往可能在很短时间内需要创建大量的连接,造成服务器响应速度过慢
小结
长连接: 连接建立成功后,可以发送多次请求和响应,等双方不进行通信的时候,服务端做好断开连接的操作
短连接: 连接建立成功后,一次请求和响应完成以后连接就会断开,每次发送请求需要先建立好连接
长连接减少了用户的等待时间,提升了访问速度,但是增加了服务端的资源开销
短连接不会占用服务端过多的资源,但是增加了用户的等待时间,减慢了访问速速
8.案例-模拟浏览器的功能实现
目标
掌握请求报文和响应报文的发送格式
案例需求
模拟浏览器请求web服务器的网页过程,使用TCP实现 HTTP协议(请求报文格式和响应报文格式)。
案例实现
import socket
if __name__ == '__main__':
# 创建tcp客户端套接字
tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接
tcp_client_socket.connect(("tlias3.boxuegu.com", 80))
# 请求行
request_line = "GET / HTTP/1.1\r\n"
# 请求头
request_header = "Host: tlias3.boxuegu.com\r\nConnection:close\r\n"
# 准备http请求报文数据
request_content = request_line + request_header + "\r\n"
# 发送http请求报文数据
tcp_client_socket.send(request_content.encode("utf-8"))
# 定义二进制响应数据的类型
result = b""
# 接收服务端http响应报文数据
while True:
# 提示: 服务端断开连接,recv会解阻塞,返回的数据长度0
# 提示: 以后可以通过Content-Length判断服务端发送数据的长度
recv_data = tcp_client_socket.recv(1024)
if recv_data:
# 表示接收到了数据
result += recv_data
# print(result)
else:
break
# 显示原始的响应报文数据
print(result)
# 解码 : 把二进制数据转成字符串
response_content = result.decode("utf-8")
# 根据指定标识数据进行分割
response_list = response_content.split("\r\n\r\n", 1)
# response_content.split("\r\n\r\n", maxsplit=1)
print(len(response_list))
print(response_list[1])
# 关闭套接字
tcp_client_socket.close()
小结
注意http请求报文的格式: 请求行 + 请求头 + \r\n + 请求体(可选)
请求行包括 1.请求方法 2.资源路径 3.http协议版本
请求头常用 1.Host:ip:port 2.Conection:keep-alive
注意http响应报文的格式: 响应行 + 响应头 + \r\n + 响应体
响应行包括 1.http协议版本 2.响应状态 3.响应状态的简单描述
响应头常用 1.Server:服务器版本 2.Content-type:text/html;charset=utf-8 3.Connection:keep-alive