它规定了浏览器和Web服务器通信数据的格式,也就是说浏览器和Web服务器通信需要使用http协议。
URL表达的意思是统一资源定位符,通俗理解就是网络资源地址,也就是我们常说的网址。
https://news.163.com/18/1122/10/E131233H.html
URL的组成部分:
域名:
域名就是IP地址的别名,它是用点进行分割使用英文字母和数字组成的名字,使用域名目的就是方便的记住某台主机IP地址。
URL的扩展:
https://news.163.com/hello.html?page=1&count=10
参数说明:
HTTP最常见的请求报文有两种:
说明:
---请求行---
GET / HTTP/1.1=> 请求方式 请求的资源路径 http协议的版本
---请求头---
Host: www.baidu.com=> 服务器的主机ip地址和端口号,如果看不到端口号,https默认是443
Connection: keep-alive=> 和服务端程序保持长连接,当客户端和服务端有一段时间没有通信,那么服务端程序会主动向客户端断开连接
Accept: text/plain, */*; q=0.01=> 告诉服务端程序,可以接受的数据类型
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4209.400=> 用户代理,客户端程序的名称,爬虫使用,可以根据是否有User-Agent进行反爬
Referer: https://www.baidu.com/?tn=98010089_dg&ch=14
Accept-Encoding: gzip, deflate, br=> 告诉服务端程序支持的压缩算法
Accept-Language: zh-CN,zh;q=0.9=> 告诉服务端程序支持的语言
Cookie: BIDUPSID=2AD97C5F09037008B8B7479292AF46DD; PSTM=1587562369; BD_UPN=1a314753; sug=3; sugstore=0; ORIGIN=0; bdime=0; BAIDUID=2AD97C5F09037008B8B7479292AF46DD:SL=0:NR=10:FG=1; BDUSS=HpCOFp1RWlobThxanZ3Ym0zNWtoUUhzUENxRHZUUTNOWktoR3A3QmFhMzdXdFplRVFBQUFBJCQAAAAAAAAAAAEAAACeAR82uqOyvMDvtcS2rLy-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPvNrl77za5eR; BDUSS_BFESS=HpCOFp1RWlobThxanZ3Ym0zNWtoUUhzUENxRHZUUTNOWktoR3A3QmFhMzdXdFplRVFBQUFBJCQAAAAAAAAAAAEAAACeAR82uqOyvMDvtcS2rLy-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPvNrl77za5eR; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; BDRCVFR[S_ukKV6dOkf]=mk3SLVN4HKm; BD_HOME=1; delPer=0; BD_CK_SAM=1; PSINO=7; BDRCVFR[EaNsStaiD7m]=mk3SLVN4HKm; COOKIE_SESSION=515_6_9_9_11_17_0_0_9_7_0_4_86791_0_0_0_1601816163_1601569596_1601816640%7C9%235901_223_1601569591%7C9; H_PS_PSSID=32755_32617_1448_32735_7544_32706_32230_7517_7605=> Cookie客户端用户身份的标识
---空行---
\r\n
---响应行---
HTTP/1.1 200 OK=> http协议版本 状态码 状态描述
Bdpagetype: 2
Bdqid: 0x97a8872b0007466a
Cache-Control: private
Connection: keep-alive=> 和客户端保持长连接
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8=> 服务器发送给浏览器的内容类型及编码格式
Date: Mon, 05 Oct 2020 05:20:48 GMT=> 服务器的时间,格林威治时间
Expires: Mon, 05 Oct 2020 05:20:47 GMT
P3p: CP=" OTI DSP COR IVA OUR IND COM "
Server: BWS/1.1=> 服务器的名称
Set-Cookie: BDRCVFR[EaNsStaiD7m]=aeXf-1x8UdYcs; path=/; domain=.baidu.com
Set-Cookie: BDSVRTM=515; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=32755_32617_1448_32735_7544_32706_32230_7517_7605; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1601875248028832205810928133114568328810
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked=> 服务器发送给客户端程序(浏览器)的数据不确定数据长度,数据发送结束的接收标识:0\r\n,Content-Length:200(字节),服务端发送给客户端的数据确定长度。内容长度这两个选项只能二选一
HTTP状态码是用于表示web服务器响应状态的3位数字代码
状态码 | 说明 |
200 | 请求成功 |
307 | 重定向 |
400 | 错误的请求,请求地址或者参数有误 |
404 | 请求资源在服务器不存在 |
500 | 服务器内部源代码出错 |
篇主要为为了实现WEB服务器,其中包含了HTTP协议的理解,以及TCP的三次握手、四次挥手等方面相关知识,同时还包含了关于web浏览器与服务器之间的通信过程。
一、web浏览器
通常在我们上网时会在浏览器的地址栏输入网址,
①、浏览器首先要对URL进行解析,
②、随后通过HTTP协议定义消息内容和步骤,即规定发送请求的格式;
③、根据服务器的域名通过操作系统下的解析器(DNS客户端)向最近的DNS服务器发送请求获取目标服务器的IP地址并存储在指定的内存空间内,,通过操作系统下的协议栈以及socket库将消息发送出去,
④、当服务器接收到请求消息会返回响应消息(该响应消息也是根据HTTP协议定义消息内容的格式)最后经过类似的过程返回给web浏览器。
接下来我们根据这几个步骤进行解析:
1.浏览器怎么对URL进行解析?
通常常用的访问数据的机制有以下几种:
HTTP协议:即 Hypertxt Transfer Protocal 超文本传送协议)访问Web服务器,例如:http://www.baidu.com/dir/file1.html
FTP协议:File Transfer Protocol,文件传输协议,主要用于文件的上传和下载,例如:ftp://ftp.glasscom.com/dir/file1.html
File协议:本地文件传输协议,例如:file://localhost/c:path/file1.zip。
maito协议:该协议可以创建一个指向电子邮件地址的超级链接,通过该链接可以在Internet中发送电子邮件。例如:maito.tone@glasscom.com等等
2、根据HTTP协议生成怎样格式的请求消息和接收的响应消息?
需要我们需要知道的是:
HTTP协议:
我们知道服务端和客户端之间进行通信过程便是:首先客户端根据HTTP协议给服务端发送请求消息,随后服务器给客户端发送响应消息。那么请求消息和响应消息具体是什么样的呢?
请求消息:
1 以下便是浏览器给服务器发送的请求消息
2 GET / HTTP/1.1
3 Host: www.baidu.com
4 Connection: keep-alive
5 Cache-Control: max-age=0
6 Upgrade-Insecure-Requests: 1
7 User-Agent: Mozilla/5.0 (Windows NT 10.0;Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99Safari/537.36
8Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
9 Accept-Encoding: gzip, deflate, br
10 Accept-Language: zh-CN,zh;q=0.9
接下来对这些信息进行解析:
第一部分:请求头行,包含请求类型、URI、HTTP协议版本;
请求信息类型通常有:get、post、put等等;
第二部分:即紧跟第一行之后的,请求头部,包含服务器所使用的说明信息;接下来解释一下这些说明信息的意思:
1、host:请求web服务器的域名地址;
2、Connection: 表示是否持久连接;即keep-alive表示持久连接;
3、Cache-Control:指定请求和响应的缓存机制;no-cache(不能缓存)、no-store(在请求消息中发送将使得请求和响应消息都不使用缓存)、max-age(客户机可以接收生存期不大于指定时间(以秒为单位)的响应)、max-stale(客户机可以接收超出超时期间的响应消息)、min-fresh(客户机可以接收响应时间小于当前时间加上指定时间的响应)、only-if-cached等等;
4、User-Agent: HTTP协议运行的浏览器类型的详细信息;比如:谷歌/67.0.3396.99
5、Accept: 指浏览器可以接收的内容类型;
6、Accept-Encoding: 客户端浏览器可以支持的web服务器返回内容压缩编码类型;
7、Accept-Language:浏览器支持的语言类型,
8、Cookie: 某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密);例如当我们上网时,某些网站能准确的推送我们想要的信息。
第三部分:"\r\n" --> 分割header和body部分的分界线
响应消息:
1 HTTP/1.1 200 OK
2 Bdpagetype: 1
3 Bdqid: 0x8bda58760001baca
4 Cache-Control: private
5 Connection: Keep-Alive
6 Content-Encoding: gzip
7 Content-Type: text/html
8 Cxy_all:baidu+10412ee70bbb9e9eec33f3dbcb3e2df7
9 Date: Wed, 18 Jul 2018 03:26:13GMT
10 Expires: Wed, 18 Jul 2018 03:25:42 GMT
11 Server: BWS/1.1
12 Set-Cookie: BDSVRTM=0; path=/
13 Set-Cookie: BD_HOME=0; path=/
14 Set-Cookie: H_PS_PSSID=1435_21118_20929; path=/; domain=.baidu.com
15 Strict-Transport-Security: max-age=172800
16 Vary:Accept-Encoding
17 X-Ua-Compatible: IE=Edge,chrome=1
18 Transfer-Encoding: chunked
响应消息的解析:
第一部分:响应头,包含:HTTP协议版本、状态码(1XX-告知请求处理进度和情况,2XX-成功,3XX-表示需要进一步操作,4XX-客户端错误;5XX-服务器错误;)
第二部分:响应头部,包含服务器发送的附加信息;这里针对几个重要的进行解析说明:https://www.cnblogs.com/mylanguage/p/5689879.html-->有详细说明。
第三部分:"\r\n" --分割header和body的分割线
第四部分:包含服务器向客户端发送的数据。
以上就请求消息和响应消息的内容格式,由浏览器或者客户端将信息根据HTTP协议转换而来。
3、怎么根据域名获取服务器的IP地址?
首先web浏览器会调用操作系统下的解析器即DNS客户端,随后由解析器发送请求给最近的DNS服务器(发送过程与C/S架构模型一样),若所需域名不在最近的DNS服务器,则由该服务器向域的DNS服务器发送询查消息,若该域名不在根域DNS服务器上,则让最近DNS服务器向其下级域发送询查消息,以此递归便能查找到该域名所在域的DNS服务器,最后由请求的DNS服务器发送响应消息到最近的DNS服务器,得到该域名的IP地址;
同时DNS服务器有一个缓存功能,可以记住之前查询过的域名,如果所查询的域名和相关信息已经在缓存中,那么久可以直接返回响应。
二、TCP的三次握手和四次挥手
首先我们需要知道在客户端与服务器基于TCP协议建立联系时需要经过三次握手,而在断开连接时需经历四次挥手的过程,那么我们来看一下该过程是怎样的?
三次握手:
解析:
首先服务器通常是处于监听的状态,而客户端通常是主动建立连接的一方,即
1、TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
2、TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
3、TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
4、TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
5、当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。
四次挥手:
同时我们需要知道的是:通常服务器不会主动断开连接,而是客户端主动断开连接。
1、客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2、服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3、客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4、服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5、客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2?
6、服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
三、实现web静态服务器
直接看示例:
import socket
import re
def server_client(server_client_socket):
T+技术学习视频资源,500+技术电子书,大量高效工具及网站,私信回复【资源】即可免费获取
HTTP 报文是在应用程序之间发送的数据块,这些数据块将通过以文本形式的元信息开头,用于 HTTP 协议交互。请求端(客户端)的 HTTP 报文叫做请求报文,响应端(服务器端)的叫做响应报文。 HTTP 报文本身是由多行(用 CR+LF 作换行符)数据构成的字符串文本。
HTTP 请求报文由请求行、请求头、空行和请求包体(body)组成。如下图所示:
真实示例:
GET / HTTP/1.1
Host: www.baidu.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="96", "Google Chrome";v="96"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: BIDUPSID=8B0207CE0B6364E5934651E84F17999B; PSTM=1619707475;
主要描述了客户端想要如何操作服务端的资源;请求行由三部分构成:
这三个部分通常使用空格(space)来分隔,最后要用 CRLF 换行表示结束。
GET / HTTP/1.1
这个请求行,结合之前的描述,意思就是“服务端妹子你好,我是客户端蛋蛋,现在我想获取网站根目录的默认信息,我这边用的协议版本是 1.1,麻烦你也要用这个版本回复我哦”
HTTP的报文头,报文头包含若干个属性,格式为“属性名:属性值”,服务端据此获取客户端的信息。与缓存相关的规则信息,均包含在header中,请求头可大致分为四种类型:通用首部字段、请求首部字段、响应首部字段、实体首部字段。这里先简单罗列,稍后做具体解释。
请求体就是 HTTP 要传输的内容,HTTP 可以承载很多类型的数字数据:图片、音频、视频、HTML 文档等。
HTTP 响应报文由状态行、响应头部、空行和响应包体(body)组成。如下图所示:
以请求 www.baidu.com为例:
HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0xfb0d743100040ad2
Cache-Control: private
Connection: keep-alive
Content-Encoding: gzip
Content-Type: text/html;charset=utf-8
Date: Fri, 24 Dec 2021 08:20:44 GMT
Expires: Fri, 24 Dec 2021 08:20:44 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=17; path=/
Set-Cookie: BD_HOME=1; path=/
Set-Cookie: H_PS_PSSID=35635_34439_35104_35628_35488_35436_35456_34584_35491_35584_35586_34873_35317_26350_35610_35562; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Traceid: 1640334044050133761018090243032019634898
X-Frame-Options: sameorigin
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked
状态行包含了 协议版本、状态码以及状态描述。
和请求报文的请求头类似,响应头也由键值对组成,每行一对,键和值用英文冒号 : 分隔。响应头域允许服务器传递不能放在状态行的附加信息,这些域主要描述服务器的信息和Request-URI进一步的信息
服务器返回给浏览器的响应信息,响应数据的格式是根据服务器来的,常见的响应数据格式有:text/html、application/json等。
常见的响应格式:
在 HTTP 的请求头和响应头中都是由首部字段来表示的,首部内容可以为客户端和服务器分别处理请求和响应提供所需要的信息。
首部字段可以分为通用首部字段、请求首部字段、响应首部字段、实体首部字段。
通用首部字段是指请求报文和响应报文都会使用到的首部字段。
先来看下都有哪些字段:
通过指定 Cache-Control 的指令,就能操作缓存的工作机制。
一般在客户端和服务端之间还存在一个缓存服务器,如果请求的资源在缓存服务器中有,就不会再请求源服务器,提高了请求响应的效率。
指令的参数可以多选,通过“,”分隔。
Cache-Control: private, max-age=0, no-cache
public 指令
Cache-Control: public
当使用 public 指令时,明确表明其他用户也可以利用缓存。
private 指令
Cache-Control: private
当指定 private 指令后,响应只以特定的用户作为对象,这与 public 指令的行为相反。
缓存服务器会对该特定用户提供资源缓存的服务,对于其他用户发送过来的请求,代理服务器则不会返回缓存。
no-cache 指令
Cache-Control: no-cache
使用 no-cache 指令可以防止从缓存中拿过期的数据。
在请求中如果包含该指令,则客户端将不会接收缓存过的响应,中间的缓存服务器会把请求转发给源服务器。
如果响应中包含该指令,缓存服务器会向源服务器进行资源有效期的确认,如果是过期的资源则不缓存。
no-store 指令
Cache-Control: no-store
该指令规定缓存不能在本地存储请求或响应的任一部分。这里我们要和上面那个 no-cache 指令要区分开,no-store才是真正不进行缓存,no-cache 只是不对过期的资源进行缓存。
Connection 有两个作用:控制不再转发给代理的首部字段、管理持久连接。
Connection: close
当服务器端想明确断开连接时,则指定 Connection 首部字段的值为 Close。
首部字段 Date 表明创建 HTTP 报文的日期和时间。
首部字段 Trailer 会事先说明在报文主体后记录了哪些首部字段。该首部字段可应用在 HTTP/1.1 版本分块传输编码时。
该字段规定了传输报文主体时采用的编码方式。 HTTP/1.1 的传输编码方式仅对分块传输编码有效。
请求首部字段是从客户端往服务器端发送请求报文中所使用的字段,用于补充请求的附加信息、客户端信息、对响应内容相关的优先级等内容。
常用字段具体说明
Accept: text/html,application/xhtml+xml,application/xml;q=0.3
该字段可以通知服务器 客户端能够接收处理的媒体类型及优先级。
比如,如果浏览器不支持 PNG 图片的显示,那 Accept 就不指定 image/png ,而指定可处理的 image/gif 和 image/jpeg 等图片类型。 若想要给显示的媒体类型增加优先级,则使用 q=来额外表示权重值。用分号(;)进行分隔。权重值 q 的范围是 0~1(可精确到小数点 后 3 位),且 1 为最大值。不指定权重 q 值时,默认权重为 q=1.0。
Accept-Charset: iso-8859-5, unicode-1-1;q=0.8
通知服务器 客户端支持的字符集及字符集的相对优先顺序。
Accept-Encoding: gzip, deflate
首部字段用来告知服务器 客户端支持的内容编码及内容编码的优先级顺序。可一次性指定多种内容编码。
Accept-Language: zh-cn,zh;q=0.7,en-us,en;q=0.3
用来告知服务器 客户端能够处理的自然 语言集(指中文或英文等),以及自然语言集的相对优先级。可一次 指定多种自然语言集。
Authorization: Basic dWVub3NlbjpwYXNzd29yZA==
首部字段 Authorization 是用来告知服务器,客户端的认证信息(证书值)。
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0)
首部字段 User-Agent 会将创建请求的浏览器和用户代理名称等信息传 达给服务器。
由网络爬虫发起请求时,有可能会在字段内添加爬虫作者的电子邮件地址。此外,如果请求经过代理,那么中间也很可能被添加上代理服务器的名称。
响应首部字段是由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加信息、服务器信息,以及对客户端的附加要求等信息。
Accept-Ranges: bytes 当不能处理范围请求时,Accept-Ranges: none
用来告知客户端服务器是否能处理范围请 求,以指定获取服务器端某个部分的资源。
Age: 600
Age 能告知客户端,源服务器在多久前创建了响应。字段值的单位为秒。
Location: http://www.usagidesign.jp/sample.html
该字段可以将响应接收方引导至某个与请求 URI 位置 不同的资源。
基本上,该字段会配合 3xx :Redirection 的响应,提供重定向的 URI。
Retry-After: 120
告知客户端应该在多久之后再次发送请求。主要 配合状态码 503 Service Unavailable 响应,或 3xx Redirect 响应一起使 用。
Server: Apache/2.2.17 (Unix)
告知客户端当前服务器上安装的 HTTP 服务器应用程序的信息。
实体首部字段是包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息。
Allow: GET, HEAD
用于通知客户端能够支持 Request-URI 指定资源的所有 HTTP 方法。
Content-Encoding: gzip
会告知客户端服务器对实体的主体部分选用的内容编码方式。
Content-Language: zh-CN
首部字段 Content-Language 会告知客户端,实体主体使用的自然语言。
Content-Length: 15000
表明了实体主体部分的大小(单位是字 节)。
Content-Type: text/html; charset=UTF-8
说明了实体主体内对象的媒体类型。
*请认真填写需求信息,我们会在24小时内与您取得联系。