简介
TCP三次握手和四次挥手不管是在开发还是面试中都是一个非常重要的知识点,它是我们优化web程序性能的基础。但是大部分教材都对这部分解释的比较抽象,本文我们就利用wireshark来抓包以真正体会整个流程的细节。
TCP/IP是一个协议族,通常分不同层次进行开发,每个层次负责不同的通信功能。包含以下四个层次:
链路层:
也称作数据链路层或者网络接口层,通常包括操作系统中的设备驱动程序和计算机中对应的网络接口卡。它们一起处理与电缆(或其他任何传输媒介)的物理接口细节。网络层:
也称作互联网层,处理分组在网络中的活动,例如分组的选路。网络层协议包括IP协议(网际协议)、ICMP协议(Internet互联网控制报文协议),以及IGMP协议(Internet组管理协议)。运输层主要为两台主机上的应用程序提供端到端的通信:
在TCP/IP协议族中,有两个互不相同的传输协议:TCP(传输控制协议)和UDP(用户数据报协议)。TCP为两台主机提供高可靠性的数据通信。他所作的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。由于运输层提供了高可靠性的端到端通信,因此应用层可以忽略所有这些细节。而另一方面,UDP则为应用层提供一种非常简单的服务。它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。任何必须的可靠性必须由应用层来提供。应用层负责处理特定的应用程序细节:
包括Telnet(远程登录)、FTP(文件传输协议)、SMTP(简单邮件传送协议)以及SNMP(简单网络管理协议)等。
wireshark抓到的包与对应的协议层如下图所示:
- Frame: 物理层的数据帧概况
- Ethernet II: 数据链路层以太网帧头部信息
- Internet Protocol Version 4: 互联网层IP包头部信息
- Transmission Control Protocol: 传输层的数据段头部信息,此处是TCP
- Hypertext Transfer Protocol: 应用层的信息,此处是HTTP协议。
TCP简介
TCP是一种面向连接(连接导向)的、可靠的基于字节流的传输层通信协议。TCP将用户数据打包成报文段,它发送后启动一个定时器,另一端收到的数据进行确认、对失序的数据重新排序、丢弃重复数据。
TCP的特点有:
1.TCP是面向连接的传输层协议
2.每一条TCP连接只能有两个端点,每一条TCP连接只能是点对点的
3.TCP提供可靠交付的服务
4.TCP提供全双工通信。数据在两个方向上独立的进行传输。因此,连接的每一端必须保持每个方向上的传输数据序号。
5.面向字节流。面向字节流的含义:虽然应用程序和TCP交互是一次一个数据块,但TCP应用程序交下来的数据仅仅是一连串的无结构的字节流。
- 源端口号:数据发起者的端口号,16bit
- 目的端口号:数据接收者的端口号,16bit
- 序号:32bit的序列号,由发送方使用
- 确认序号:32bit的确认号,是接收数据方期望收到发送方的下一个报文段的序号,因此确认序号应当是上次已成功收到数据字节序号加1。
- 首部长度:首部中32bit字的数目,可表示15*32bit=60字节的首部。一般首部长度为20字节。
- 保留:6bit, 均为0
- 紧急URG:当URG=1时,表示报文段中有紧急数据,应尽快传送。
- 确认比特ACK:ACK = 1时代表这是一个确认的TCP包,取值0则不是确认包。
- 推送比特PSH:当发送端PSH=1时,接收端尽快的交付给应用进程。
- 复位比特(RST):当RST=1时,表明TCP连接中出现严重差错,必须释放连接,再重新建立连接。
- 同步比特SYN:在建立连接是用来同步序号。SYN=1, ACK=0表示一个连接请求报文段。SYN=1,ACK=1表示同意建立连接。
- 终止比特FIN:FIN=1时,表明此报文段的发送端的数据已经发送完毕,并要求释放传输连接。
- 窗口:用来控制对方发送的数据量,通知发放已确定的发送窗口上限。
- 检验和:该字段检验的范围包括首部和数据这两部分。由发端计算和存储,并由收端进行验证。
- 紧急指针:紧急指针在URG=1时才有效,它指出本报文段中的紧急数据的字节数。
- 选项:长度可变,最长可达40字节。
三次握手
根据下面这幅图我们来看一下TCP三次握手。p.s: 每个箭头代表一次握手。
tcp三次握手
第一次握手
client发送一个SYN=1(seq=X)包给server,然后等待server的ACK回复,进入SYN-SENT状态。p.s: SYN为synchronize的缩写,ACK为acknowledgment的缩写。
第二次握手
server接收到SYN=1(seq=X)包后就返回一个ACK=1(ack=X+1)包以及一个自己的SYN=1(seq=Y)包,然后等待client的ACK回复,server进入SYN-RECIVED状态。
第三次握手
client接收到server发回的ACK=1(ack=X+1)包后,进入ESTABLISHED状态。然后根据server发来的SYN=1(seq=Y)包,返回给等待中的server一个ACK=1(ack=Y+1)包。等待中的server收到ACK回复,也把自己的状态设置为ESTABLISHED。到此TCP三次握手完成,client与server可以正常进行通信了。
为什么要进行三次握手
我们来看一下为什么需要进行三次握手,两次握手难道不行么?这里我们用一个生活中的具体例子来解释就很好理解了。我们可以将三次握手中的客户端和服务器之间的握手过程比喻成A和B通信的过程:
在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。
在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。
在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。
wireshark解析
第一次握手
客户端向服务器发送连接请求包,标志位SYN(同步序号)置为1,序号为X=0。
第二次握手
服务器收到客户端发过来报文,由SYN=1知道客户端要求建立联机。向客户端发送一个SYN和ACK都置为1的TCP报文,设置初始序号Y=0,将确认序号(Acknowledgement Number)设置为客户的序列号加1,即X+1 = 0+1=1, 如下图。
第三次握手
客户端收到服务器发来的包后检查确认序号(Acknowledgement Number)是否正确,即第一次发送的序号加1(X+1=1)。以及标志位ACK是否为1。若正确,服务器再次发送确认包,ACK标志位为1,SYN标志位为0。确认序号(Acknowledgement Number)=Y+1=0+1=1,发送序号为X+1=1。客户端收到后确认序号值与ACK=1则连接建立成功,可以传送数据了。