HTTP协议详解1--工作原理

一、简介

HTTP是个应用层协议。HTTP无需操心网络通信的具体细节;它把联网的细节都交给了通用、可选的因特网传输协议TCP/IP。只要建立了TCP连接,客户端和服务器端之间的报文交换就不会丢失、不会被破坏,也不会在接收时出现错序了。

用网络术语来说,HTTP协议位于TCP的上层。HTTP使用TCP来传输其报文数据。

在HTTP客户端向服务器发送报文之前,需要用网际协议(Internet Protocol,IP)地址和端口号在客户端和服务器之间建立一条TCP/IP连接。基本步骤如下图:

a)浏览器从URL中解析出服务器的主机名;
b)浏览器将服务器的主机名转换成服务器的IP地址;
c)浏览器将端口号(如果有的话)从URL中解析出来;
d)浏览器建立一条与web服务器的TCP连接;
e)浏览器向服务器发送一条HTTP请求报文;
f)服务器向浏览器回送一条HTTP响应报文;
g)关闭连接,浏览器显示文档。

二、TCP连接

在任意时刻计算机都可以有几条TCP连处于打开状态,TCP是通过端口号来保持所有这些连接持续不断地运行。

TCP连接是通过4个值来识别的:<源IP地址、源端口号、目的IP地址、目的端口号>,这4个值唯一定义了一条连接。

HTTP要传送一条报文时,会以流的形式将报文数据的内容通过一条打开的TCP连接按序传输。TCP收到数据流之后,会将数据流砍成被称作段的小数据块,并将段封闭在IP分组中,通过黑硬因特网传输,如:

当然,所有这些工作都是由TCP/IP软件来处理的,HTTP程序员什么都看不到。(下面小节将会介绍到TCP连接中著名的“三次握手”与“四次挥手”)

如上图,每个IP分组中都包括:

  • 一个IP分组首部(通常为20字节)。
    包含了源和目的IP地址、长度和其它一些标记
  • 一个TCP段首部(通常为20字节)。
    包含了TCP端口号、TCP控制标记,以及用于数据排序和完整性检查的一些数字值
  • 一个TCP数据块(0个或多个字节)。
三、HTTP请求与响应的过程

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

当目的主机收到一个以太网数据帧时,数据就开始从协议栈中由底向上升,同时去掉各层协议加上的报文首部。每层协议盒都要去检查报文首部中的协议标识,以确定接收数据的上层协议。这个过程称作分用(Demultiplexing)。

四、TCP的三次握手

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

  • 第一次握手
    请求新的TCP连接时,客户端要向服务器发送一个连接请求报文段。这个报文段中设置了一个特殊SYN标记,说明这是一个连接请求。将SYN位置为1,Sequence Number为x。然后,客户端进入SYN_SEND状态,等待服务器的确认。

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

  • 第三次握手
    客户端收到服务器的SYN+ACK报文段。然后将ACK设置为y+1,向服务器发送ACK报文段,这个报文段发送完毕以后,客户端和服务器端都进入ESTABLISHED状态,完成TCP三次握手。(现代的TCP栈都允许客户端在这个请求报文中发送数据。)

TCP标示:
SYN(synchronous建立联机)
ACK(acknowledgement 确认)
Sequence number(顺序号码)

为什么要三次握手:

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

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

下图是对TCP三次握手更加形象的一个解说:

五、TCP的四次挥手

当客户端和服务器通过三次握手建立了TCP连接以后,当数据传送完毕,肯定是要断开TCP连接的啊。那对于TCP的断开连接,这里就有了神秘的“四次分手”。

  • 第一次挥手
    主机1(可以使客户端,也可以是服务器端),设置Sequence Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这表示主机1没有数据要发送给主机2了;

  • 第二次挥手
    主机2收到了主机1发送的FIN报文段,向主机1回一个ACK报文段,ACK为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我“同意”你的关闭请求;

  • 第三次挥手
    主机2向主机1发送FIN报文段,请求关闭连接,同时主机2进入LAST_ACK状态;

  • 第四次分手
    主机1收到主机2发送的FIN报文段,向主机2发送ACK报文段,然后主机1进入TIME_WAIT状态;主机2收到主机1的ACK报文段以后,就关闭连接;此时,主机1等待2MSL(最大报文段生存时间)后依然没有收到回复,则证明Server端已正常关闭,那好,主机1也可以关闭连接了。

解说:

假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,“告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息”。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,“告诉Client端,好了,我这边数据发完了,准备好关闭连接了”。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,“就知道可以断开连接了”。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

【注意】中断连接端可以是Client端,也可以是Server端。

六、一个完整的TCP连接

建立TCP需要三次握手才能建立,然后可以开始数据传输,而断开连接则需要四次挥手。

整个过程如下图所示:

参考

《HTTP权威指南》 David Gourley, Brian Totty, Marjorie Sayer, Sailu Reddy, Ansbu Aggarwal 著 陈涓 赵振平 译
简书博客:https://www.jianshu.com/p/c1d6a294d3c0

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值