http连接过程

493 阅读14分钟

一、HTTP 请求和响应步骤

二、TCP/IP 协议

TCP/IP 协议模型(Transmission Control Protocol/Internet Protocol),包含了一系列构成互联网基础的网络协议,是 Internet 的核心协议,通过 20 多年的发展已日渐成熟,并被广泛应用于局域网和广域网中(如果局域网是小溪,很多条小溪就汇聚成大的干流,比如长江、黄河,干流就是广域网,然后再流入大海,大海就是互联网),目前已成为事实上的国际标准。TCP/IP 协议簇是一组不同层次上的多个协议的组合,通常被认为是一个四层协议系统,与 OSI 的七层模型相对应(OSI 七层模型学习笔记)。

HTTP 协议就是基于 TCP/IP 协议模型来传输信息的。

(1). 链路层

也称作数据链路层或网络接口层(在第一个图中为网络接口层和硬件层),通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。ARP(地址解析协议)和 RARP(逆地址解析协议)是某些网络接口(如以太网和令牌环网)使用的特殊协议,用来转换 IP 层和网络接口层使用的地址。

(2). 网络层

也称作互联网层(在第一个图中为网际层),处理分组在网络中的活动,例如分组的选路。在 TCP/IP 协议族中,网络层协议包括 IP 协议(网际协议),ICMP 协议(Internet 互联网控制报文协议),以及 IGMP 协议(Internet 组管理协议)。

IP 是一种网络层协议,提供的是一种不可靠的服务,它只是尽可能快地把分组从源结点送到目的结点,但是并不提供任何可靠性保证。同时被 TCP 和 UDP 使用。TCP 和 UDP 的每组数据都通过端系统和每个中间路由器中的 IP 层在互联网中进行传输。

ICMP 是 IP 协议的附属协议。IP 层用它来与其他主机或路由器交换错误报文和其他重要信息。

IGMP 是 Internet 组管理协议。它用来把一个 UDP 数据报多播到多个主机。

(3). 传输层

主要为两台主机上的应用程序提供端到端的通信。在 TCP/IP 协议族中,有两个互不相同的传输协议:TCP(传输控制协议)和 UDP(用户数据报协议)。

TCP 为两台主机提供高可靠性的数据通信。它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。为了提供可靠的服务,TCP 采用了超时重传、发送和接收端到端的确认分组等机制。

UDP 则为应用层提供一种非常简单的服务。它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。一个数据报是指从发送方传输到接收方的一个信息单元(例如,发送方指定的一定字节数的信息)。UDP 协议任何必需的可靠性必须由应用层来提供。
(4). 应用层

应用层决定了向用户提供应用服务时通信的活动。TCP/IP 协议族内预存了各类通用的应用服务。包括 HTTP,FTP(File Transfer Protocol,文件传输协议),DNS(Domain Name System,域名系统)服务。

当应用程序用 TCP 传送数据时,数据被送入协议栈中,然后逐个通过每一层直到被当作一串比特流送入网络。其中每一层对收到的数据都要增加一些首部信息(有时还要增加尾部信息),该过程如图所示。

当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由底向上升,同时去掉各层协议加上的报文首部。每层协议盒都要去检查报文首部中的协议标识,以确定接收数据的上层协议。这个过程称作分用(Demultiplexing)。协议是通过目的端口号、源 I P 地址和源端口号进行解包的。

通过以上步骤我们从 TCP/IP 模型的角度来理解了一次 HTTP 请求与响应的过程。

下面这张图更清楚明白:

下面具体来看如何进行一步步操作的。

三、TCP 三次握手

TCP 是面向连接的,无论哪一方向另一方发送数据之前,都必须先在双方之间建立一条连接。在 TCP/IP 协议中,TCP 协议提供可靠的连接服务,连接是通过三次握手进行初始化的。三次握手的目的是同步连接双方的序列号和确认号并交换 TCP 窗口大小信息。

第一次握手:建立连接。客户端发送连接请求报文段,将 SYN 位置为 1,Sequence Number 为 x;然后,客户端进入 SYN_SEND 状态,等待服务器的确认;

第二次握手:服务器收到 SYN 报文段。服务器收到客户端的 SYN 报文段,需要对这个 SYN 报文段进行确认,设置 Acknowledgment Number 为 x+1(Sequence Number+1);同时,自己自己还要发送 SYN 请求信息,将 SYN 位置为 1,Sequence Number 为 y;服务器端将上述所有信息放到一个报文段(即 SYN+ACK 报文段)中,一并发送给客户端,此时服务器进入 SYN_RECV 状态;

第三次握手:客户端收到服务器的 SYN+ACK 报文段。然后将 Acknowledgment Number 设置为 y+1,向服务器发送 ACK 报文段,这个报文段发送完毕以后,客户端和服务器端都进入 ESTABLISHED 状态,完成 TCP 三次握手。

为什么要三次握手

为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误。

具体例子:“已失效的连接请求报文段”的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用 “三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用“三次握手” 的办法可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。”

四、HTTP 协议

Http 是什么?

通俗来讲,他就是计算机通过网络进行通信的规则,是一个基于请求与响应,无状态的,应用层的协议,常基于 TCP/IP 协议传输数据。目前任何终端(手机,笔记本电脑。。)之间进行任何一种通信都必须按照 Http 协议进行,否则无法连接。

四个基于:

**请求与响应:**客户端发送请求,服务器端响应数据

**无状态的:**协议对于事务处理没有记忆能力,客户端第一次与服务器建立连接发送请求时需要进行一系列的安全认证匹配等,因此增加页面等待时间,当客户端向服务器端发送请求,服务器端响应完毕后,两者断开连接,也不保存连接状态,一刀两断!恩断义绝!从此路人!下一次客户端向同样的服务器发送请求时,由于他们之前已经遗忘了彼此,所以需要重新建立连接。

**应用层:**Http 是属于应用层的协议,配合 TCP/IP 使用。

**TCP/IP:**Http 使用 TCP 作为它的支撑运输协议。HTTP 客户机发起一个与服务器的 TCP 连接,一旦连接建立,浏览器(客户机)和服务器进程就可以通过套接字接口访问 TCP。

针对无状态的一些解决策略:

有时需要对用户之前的 HTTP 通信状态进行保存,比如执行一次登陆操作,在 30 分钟内所有的请求都不需要再次登陆。于是引入了 Cookie 技术。

HTTP/1.1 想出了持久连接(HTTP keep-alive)方法。其特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态,在请求首部字段中的 Connection: keep-alive 即为表明使用了持久连接。
等等还有很多。。。。。。

下面开始讲解重头戏:HTTP 请求报文,响应报文,对应于上述步骤的 2,3,4,5,6。

HTTP 报文是面向文本的,报文中的每一个字段都是一些 ASCII 码串,各个字段的长度是不确定的。HTTP 有两类报文:请求报文和响应报文。

五、HTTP 请求报文

一个 HTTP 请求报文由请求行(request line)、请求头部(header)、空行和请求数据 4 个部分组成,下图给出了请求报文的一般格式。

请求图示

  1. 请求行

请求行分为三个部分:请求方法、请求地址和协议版本

请求方法

HTTP/1.1 定义的请求方法有 8 种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。

最常的两种 GET 和 POST,如果是 RESTful 接口的话一般会用到 GET、POST、DELETE、PUT。

请求地址

URL: 统一资源定位符,是一种自愿位置的抽象唯一识别方法。

组成:<协议>://< 主机 >:< 端口 >/< 路径 >

端口和路径有时可以省略(HTTP 默认端口号是 80)

如下例:

有时会带参数,GET 请求

协议版本

协议版本的格式为:HTTP / 主版本号. 次版本号,常用的有 HTTP/1.0 和 HTTP/1.1

  1. 请求头部

请求头部为请求报文添加了一些附加信息,由 “名 / 值” 对组成,每行一对,名和值之间使用冒号分隔。

常见请求头如下:

请求头部的最后会有一个空行,表示请求头部结束,接下来为请求数据,这一行非常重要,必不可少。

  1. 请求数据

可选部分,比如 GET 请求就没有请求数据。

下面是一个 POST 方法的请求报文:

POST  /index.php HTTP/1.1    请求行
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:10.0.2) Gecko/20100101 Firefox/10.0.2  请求头
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: zh-cn,zh;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Referer: http://localhost/
Content-Length:25
Content-Type:application/x-www-form-urlencoded
  空行
username=aa&password=1234  请求数据

六、HTTP 响应报文

HTTP 响应报文主要由状态行、响应头部、空行以及响应数据组成。

  1. 状态行

由 3 部分组成,分别为:协议版本,状态码,状态码描述。

其中协议版本与请求报文一致,状态码描述是对状态码的简单描述,所以这里就只介绍状态码。

状态码

状态代码为 3 位数字。
1xx:指示信息 -- 表示请求已接收,继续处理。
2xx:成功 -- 表示请求已被成功接收、理解、接受。
3xx:重定向 -- 要完成请求必须进行更进一步的操作。
4xx:客户端错误 -- 请求有语法错误或请求无法实现。
5xx:服务器端错误 -- 服务器未能实现合法的请求。

下面列举几个常见的:

  1. 响应头部

与请求头部类似,为响应报文添加了一些附加信息

常见响应头部如下:

  1. 响应数据

用于存放需要返回给客户端的数据信息。

下面是一个响应报文的实例:

HTTP/1.1 200 OK  状态行
Date: Sun, 17 Mar 2017 08:12:54 GMT  响应头部
Server: Apache/2.2.8 (Win32) PHP/5.2.5
X-Powered-By: PHP/5.2.5
Set-Cookie: PHPSESSID=c0huq7pdkmm5gg6osoe3mgjmm3; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Content-Length: 4393
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=utf-8
  空行

  响应数据 HTTP 响应示例 < title> </head> <body> Hello HTTP! </body> </html> </blockquote> <p>关于请求头部和响应头部的知识点很多,这里只是简单介绍。</p> <p>通过以上步骤,数据已经传递完毕,HTTP/1.1 会维持持久连接,但持续一段时间总会有关闭连接的时候,这时候据需要断开 TCP 连接。</p> <h2><span class="prefix"></span><span class="content">七、TCP 四次挥手</span><span class="suffix"></span></h2> <p>当客户端和服务器通过三次握手建立了 TCP 连接以后,当数据传送完毕,肯定是要断开 TCP 连接的啊。那对于 TCP 的断开连接,这里就有了神秘的 “四次分手”。</p> <p><img src="https://pic2.zhimg.com/v2-75cc9591e92108c1ead0787a4066d49d_b.jpg" alt=""><img src="https://pic2.zhimg.com/v2-75cc9591e92108c1ead0787a4066d49d_r.jpg" alt="">TCP 的四次挥手</p> <p>第一次分手:主机 1(可以使客户端,也可以是服务器端),设置 Sequence Number,向主机 2 发送一个 FIN 报文段;此时,主机 1 进入 FIN_WAIT_1 状态;这表示主机 1 没有数据要发送给主机 2 了;</p> <p>第二次分手:主机 2 收到了主机 1 发送的 FIN 报文段,向主机 1 回一个 ACK 报文段,Acknowledgment Number 为 Sequence Number 加 1;主机 1 进入 FIN_WAIT_2 状态;主机 2 告诉主机 1,我 “同意” 你的关闭请求;</p> <p>第三次分手:主机 2 向主机 1 发送 FIN 报文段,请求关闭连接,同时主机 2 进入 LAST_ACK 状态;</p> <p>第四次分手:主机 1 收到主机 2 发送的 FIN 报文段,向主机 2 发送 ACK 报文段,然后主机 1 进入 TIME_WAIT 状态;主机 2 收到主机 1 的 ACK 报文段以后,就关闭连接;此时,主机 1 等待 2MSL 后依然没有收到回复,则证明 Server 端已正常关闭,那好,主机 1 也可以关闭连接了。</p> <h3><span class="prefix"></span><span class="content">为什么要四次分手</span><span class="suffix"></span></h3> <p>TCP 协议是一种面向连接的、可靠的、基于字节流的运输层通信协议。TCP 是全双工模式,这就意味着,当主机 1 发出 FIN 报文段时,只是表示主机 1 已经没有数据要发送了,主机 1 告诉主机 2,它的数据已经全部发送完毕了;但是,这个时候主机 1 还是可以接受来自主机 2 的数据;当主机 2 返回 ACK 报文段时,表示它已经知道主机 1 没有数据发送了,但是主机 2 还是可以发送数据到主机 1 的;当主机 2 也发送了 FIN 报文段时,这个时候就表示主机 2 也没有数据要发送了,就会告诉主机 1,我也没有数据要发送了,之后彼此就会愉快的中断这次 TCP 连接。</p> <p>通过以上步骤便完成了 HTTP 的请求和响应,进行了数据传递,这其中涉及到需要知识点,都进行了逐一了解。</p>