第十七篇:WEB服务器之HTTP协议
本篇主要为为了实现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协议给服务端发送请求消息,随后服务器给客户端发送响应消息。那么请求消息和响应消息具体是什么样的呢?
请求消息:
# 以下便是浏览器给服务器发送的请求消息 GET / HTTP/1.1
Host: www.baidu.com
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/67.0.3396.99 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 #接下来对这些信息进行解析:
第一部分:请求头行,包含请求类型、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部分的分界线
响应消息:
# 响应消息 HTTP/1.1 200 OK
Bdpagetype: 1
Bdqid: 0x8bda58760001baca
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html
Cxy_all: baidu+10412ee70bbb9e9eec33f3dbcb3e2df7
Date: Wed, 18 Jul 2018 03:26:13 GMT
Expires: Wed, 18 Jul 2018 03:25:42 GMT
Server: BWS/1.1
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1435_21118_20929; path=/; domain=.baidu.com
Strict-Transport-Security: max-age=172800
Vary: Accept-Encoding
X-Ua-Compatible: IE=Edge,chrome=1
Transfer-Encoding: chunked # 响应消息的解析:
第一部分:响应头,包含:HTTP协议版本、状态码(1XX-告知请求处理进度和情况,2XX-成功,3XX-表示需要进一步操作,4XX-客户端错误;5XX-服务器错误;)
第二部分:响应头部,包含服务器发送的附加信息;这里针对几个重要的进行解析说明:
https://www.cnblogs.com/mylanguage/p/5689879.html -->有详细说明。
第三部分:"\r\n" --分割header和body的分割线
第四部分:包含服务器向客户端发送的数据。
以上就请求消息和响应消息的内容格式,由浏览器或者客户端将信息根据HTTP协议转换而来。
3、怎么根据域名获取服务器的IP地址?
前面便提到了要想实现两台终端之间的通信必须知道对方的IP地址和端口号,但是我们在浏览器地址栏输入的仅是域名,那么我们怎么获得目标服务器的IP地址呢?
首先web浏览器会调用操作系统下的解析器即DNS客户端,随后由解析器发送请求给最近的DNS服务器(发送过程与C/S架构模型一样),若所需域名不在最近的DNS服务器,则由该服务器向域的DNS服务器发送询查消息,若该域名不在根域DNS服务器上,则让最近DNS服务器向其下级域发送询查消息,以此递归便能查找到该域名所在域的DNS服务器,最后由请求的DNS服务器发送响应消息到最近的DNS服务器,得到该域名的IP地址;
同时DNS服务器有一个缓存功能,可以记住之前查询过的域名,如果所查询的域名和相关信息已经在缓存中,那么久可以直接返回响应。
二、TCP的三次握手和四次挥手
首先我们需要知道在客户端与服务器基于TCP协议建立联系时需要经过三次握手,而在断开连接时需经历四次挥手的过程,那么我们来看一下该过程是怎样的?
三次握手:
解析:
首先服务器通常是处于监听的状态,而客户端通常是主动建立连接的一方,即
- TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
- TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
- TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
- TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
- 当服务器收到客户端的确认后也进入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∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
- 6、服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。
三、实现web静态服务器
直接看示例:
import socket
import re def server_client(server_client_socket):
"""接收来自浏览器的数据和发送报文""" # 对接收到的请求消息进行解析
request = server_client_socket.recv(1024).decode("utf-8")
# 请求消息头部格式大概为 : GET /index.html HTTP/1.1
request_lines = request.splitlines() # 将接收到的信息按行分割,并返回列表
ret = re.match(r"[^/]+(/[^ ]*)",request_lines[0]) # 若正则表达式匹配成功有返回值,则检测是由为 "/"或者空字符,则设置默认文件为/index.html文件
if ret:
filename = ret.group(1)
if filename == "/" or filename == "":
filename = "/index.html"
# print(request) respone = "HTTP/1.1 200 OK\r\n"
respone += "\r\n"
# respone += "<h2>hello world</h2>" # 检测服务器中是否有该文件,有则发生内容,无则返回错误
try:
f = open("html"+ filename,"rb")
except:
respone = "HTTP/1.1 404 Not found file \r\n"
respone += "\r\n"
respone += "<h1>Not found File</h1>"
respone = respone.encode("utf-8")
else:
file_content = f.read()
f.close()
respone = respone.encode("utf-8") + file_content # 字节之间的拼接 server_client_socket.send(respone) server_client_socket.close() def main():
# 1、创建套接字对象
server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 2、绑定本地信息
server_socket.bind(("",6969))
# 3、监听
server_socket.listen(128)
while True:
# 4、等待客户端连接
server_client_socket,client_addr = server_socket.accept()
# 5、服务客户端
server_client(server_client_socket) server_socket.close() if __name__ == "__main__":
main()
这样就实现了一个静态的web服务器,可以接收web浏览器的请求,对请求的数据进行解析,通过正则表达式得到需要浏览器请求的页面的文件名,通过文件的读取得到数据,并将内容符合给web浏览器。
第十七篇:WEB服务器之HTTP协议的更多相关文章
- Web服务器之iis,apache,tomcat三者之间的比较
IIS-Apache-Tomcat的区别 IIS与Tomcat的区别 IIS是微软公司的Web服务器.主要支持ASP语言环境. Tomcat是Java Servlet 2.2和JavaServer P ...
- 跟我学SpringCloud | 第十七篇:服务网关Zuul基于Apollo动态路由
目录 SpringCloud系列教程 | 第十七篇:服务网关Zuul基于Apollo动态路由 Apollo概述 Apollo相比于Spring Cloud Config优势 工程实战 示例代码 Spr ...
- Web服务器之Nginx详解(理论部分)
大纲 一.前言 二.Web服务器提供服务的方式 三.多进程.多线程.异步模式的对比 四.Web 服务请求过程 五.Linux I/O 模型 六.Linux I/O 模型具体说明 七.Linux I/O ...
- 【转】Web服务器之Nginx详解(理论部分)
大纲 一.前言 二.Web服务器提供服务的方式 三.多进程.多线程.异步模式的对比 四.Web 服务请求过程 五.Linux I/O 模型 六.Linux I/O 模型具体说明 七.Linux I/O ...
- Web服务器之Nginx详解(操作部分)
大纲 一.前言 二.Nginx 安装与配置 三.Nginx 配置文件详解 四.Nginx 命令参数 五.配置Nginx提供Web服务 六.配置Nginx的虚拟主机 七.配置Nginx的用户认证 八.配 ...
- web服务器之nginx与apache
最近准备架设php的web服务器,以下内容可供参考. 1.nginx相对于apache的优点: 轻量级,同样起web 服务,比apache占用更少的内存及资源 抗并发,nginx 处理请求是异步非阻塞 ...
- web服务器之nginx和apache的区别
① apache属于重量级的服务器,nginx属于轻量级的服务器; 区别在于对一些功能的支持,比如: pathinfo,php模块方面 ② nginx抗高并发能力强. 由于nginx采用的是异步非阻 ...
- java基础76 web服务器之Tomcat服务器
(注:本文是以“压缩版Tomcat”为例,展开描述的) 一.Tomcat服务器的介绍 1.服务器 1.1.服务器的种类 从物理上讲:服务器就是一台pc机器.至少8核/8G以上.内存至少用T来计算.宽带 ...
- 常用的系统架构 web服务器之iis,apache,tomcat三者之间的比较
常用的系统架构是: Linux + Apache + PHP + MySQL Linux + Apache + Java (WebSphere) + Oracle Windows Server 200 ...
随机推荐
- 123457123456#0#-----com.tym.myNewShiZi45--前拼后广--识字tym
com.tym.myNewShiZi45--前拼后广--识字tym
- intellij maven配置与使用
目录 intellij maven配置与使用 Maven 常用设置介绍 Maven 骨架创建 Java Web 项目 Maven 组件来管理项目 @(目录) intellij maven配置与使用 M ...
- clientHeight,offsetHeight,scrollHeight迷一样的三个值
https://blog.csdn.net/qq_39083004/article/details/78498178 https://www.imooc.com/article/17571 推荐 o ...
- mongodb4.0 安装
下载: wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-4.0.9.tgz 解压缩 tar -zxvf mongodb-linux ...
- Charles 抓包配置
本文参考:charles 抓包配置 proxy setting (代理设置) 设置的主界面如下: 动态端口 启用动态端口选项来监听动态端口,每次查询启动时选择.这样可以避免与计算机上可能运行的其他网络 ...
- C# 人工智能开源库生物特征
C# 人工智能开源库生物特征 Machine learning made in a minute http://accord-framework.net/ Accord.NET是AForge.NET框 ...
- 038 Android Magicindicator开源框架实现viewpager底部圆形指示器
1.Magicindicator介绍 Magicindicator是一个强大.可定制.易扩展的 ViewPager 指示器框架.是ViewPagerIndicator.TabLayout.PagerS ...
- [转帖]Linux系统进程的知识总结,进程与线程之间的纠葛...
Linux系统进程的知识总结,进程与线程之间的纠葛... https://cloud.tencent.com/developer/article/1500509 当一个程序开始执行后,在开始执行到执行 ...
- 多线程(11) — NIO
Java NIO是new IO的简称,是一种可以替代Java IO的一套新的IO机制.它提供了一套不同于Java标准IO的操作机制,严格来说,NIO与并发并无直接关系,但是使用NIO技术可以大大提高线 ...
- 暑期ACM集训
2019-07-17 08:42:11 这是总结昨天的做题情况 总体来说,好久的没做题了,实力下降了许多,这一个月假又学习吧!!!! A - Ropewalkers Polycarp decided ...