[Python之路] HTTP协议复习笔记

一、HTTP请求的直观了解

我们使用网络调试助手来模拟一个TCP Server,然后使用浏览器来访问对应的IP:Port。

 

 

 启动后,我们使用谷歌浏览器来访问192.168.1.8:8080:

 

我们可以看到浏览器一直在等待服务器返回数据。

我们可以在 网络调试助手上看到接收到的HTTP请求

GET / HTTP/1.1
Host: 192.168.1.8:8080
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9

解释:

1.GET是浏览器向服务器请求数据的一种方式,一般有GET和POST。

2.GET后面是一个空格(不可少)

3.空格后面的"/"表示请求的内容,如果我们请求时使用http://192.168.1.8:8080/index.html,则这里就是"/index.html"。

4."HTTP/1.1"是使用的HTTP协议版本,这里是1.1版本。

5.Host是请求的目的,即服务器地址。

6.Connection是链接的类别,keep-alive是长连接。

7.User-Agent是浏览器客户端的版本信息,普通用户使用标准浏览器访问时,都会有这个字段,如果没有该字段说明可能是爬虫程序。主要用于反爬虫。

8.Accept表示浏览器可以接受的数据类型。

9.Accept-Encoding表示浏览器可以接受的数据压缩格式(用于数据量比较大时,服务器进行压缩传输)。

10.Accept-Language表示浏览器可以接受的文本语言。

 

二、观察HTTP的响应头

我们使用谷歌浏览器访问百度首页,并打开F12来查看交互流程:

 

可以在其中找到我们需要的请求头、响应头信息:

请求头:

GET / HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: BAIDUID=F5E42E8A08547BB39711F21232455CB0:FG=1; BIDUPSID=F5E42E8A08547BB39711F21232455CB0; PSTM=1569579669; sugstore=1; MCITY=-75%3A; BD_UPN=12314753; H_PS_PSSID=1451_21123_29568_29221_26350; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; delPer=0; BD_CK_SAM=1; PSINO=7; BDSVRTM=137; BCLID=10618646423443952060; BDSFRCVID=g8COJeCmH6VwoRJwYAdxT9UxGmKK0gOTHllvFiwowP8T7G8VJeC6EG0Ptf8g0KubFTPRogKK0gOTH6KF_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tJkD_I_hJKt3qn7I5KToh4Athxob2bbXHDo-LIvjfpOcOR5JhfA-3R-e046fXxobMNP8-4nTalvvhb3O3M7ShbKzMqJy-h8OQnvxVUQF5l8-sq0x0bOte-bQypoa0q3TLDOMahkM5h7xOKQoQlPK5JkgMx6MqpQJQeQ-5KQN3KJmfbL9bT3YjjISKx-_J6LeJRbP

响应头:

HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0xda48b61a00089ab4
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html
Cxy_all: baidu+1b1b86535b4f42dc5821baca812fd9c4
Date: Wed, 27 Nov 2019 15:07:07 GMT
Expires: Wed, 27 Nov 2019 15:06:46 GMT
Server: BWS/1.1
Set-Cookie: delPer=0; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1451_21123_29568_29221_26350; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1574867227025529191415729021921377426100
Vary: Accept-Encoding
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked

响应头解释:

1.HTTP/1.1 200 OK表示我们要请求的页面存在,可以成功返回。

2.Content-Encoding表示返回数据使用的压缩格式为gzip。

3.Date表示服务器当前的时间。

4.Content-Type表示返回数据的格式为text/html,这里也可能附带编码,例如utf-8。

5.Server表示服务器的名称和版本,这里的BWS/1.1是百度服务器的名称和版本。一般情况下为Apache、Nginx、Tengine等。

6.Set-Cookie见后面的详细解释...

 

Set-Cookie解释:

实际例子:假设我们使用JD搜索了"刮胡刀",为什么第二天我们再次打开JD的时候,就会给我们推送很多刮胡刀的广告。

1.第一次访问JD的时候,我们浏览器发送的请求头是很短的,只有最基本的一些信息,例如请求目录、浏览器版本等。

2.JD服务器再响应时,会检查请求头中是否存在Cookie,如果不存在,则会在响应头中使用Set-Cookie关键字传输一些信息给浏览器。例如上述响应头中的"Set-Cookie: H_PS_PSSID=1451_21123_29568_29221_26350; path=/; domain=.baidu.com"

3.Set-Cookie中的H_PS_PSSID、path和domain都是key,而后面的1451_***_26350等都是value。浏览器会将这些Cookie数据存在本地缓存中,domain表示下次访问关于baidu域名的网页时,将携带这些Cookie在请求头中。

4.第二天访问JD时,浏览器就将前一次存放的Cookie信息放在请求头中,传递给了服务器。其中的一些Cookie可能就是代表这个未登陆的用户ID(例如上述请求头中Cookie里的BAIDUID),服务器通过这个Cookie中携带的ID,就知道是昨天搜索刮胡刀的人,那么就可以给他推送刮胡刀广告。

 

三、查看响应体

在响应头后面空一行(浏览器就是根据这个空行来分隔响应头和响应体)之后,就是响应体。响应体主要是服务器返回的真正的页面信息,一般是html文本。

我们可以在F12中看到响应体:

 

四、使用python实现一个简单的静态Server

import socket

leo_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口8900
leo_sock.bind(('192.168.1.8', 8900))

leo_sock.listen(5)
print('starting....')
conn, addr = leo_sock.accept()
print(conn)
print('client addr', addr)
print('ready to read msg')
client_msg = conn.recv(1024)
print('client msg: %s' % client_msg)
# 换行符是\r\n
reponse_msg = "HTTP/1.1 200 OK\r\n\r\n<h1>hahaha</h1>"
# TCP网络传输二进制数据
conn.send(reponse_msg.encode(encoding="utf-8"))

# 关闭连接
conn.close()
# 关闭socket
leo_sock.close()

使用浏览器访问192.168.1.8:8900:

 

服务器成功返回了内容。

posted @ 2019-11-27 22:19  风间悠香  阅读(505)  评论(0编辑  收藏  举报