TCP三次握手详细介绍缓存
1.TCP/IP协议简单介绍:服务器
TCP/IP是一个协议族,一般分不一样层次进行工做,每一个层次负责不一样的通讯功能。包含如下四个层次:网络
应用层:(http、telnet、Email、dns等协议)socket
传输层:(tcp和udp)tcp
网络层:(ip、icmp、rarp、bootp)ide
链路层:(设备驱动程序及接口卡)函数
1).链路层,也称做数据链路层或者网络接口层,一般包括操做系统中的设备驱动程序和计算机中对应的网络接口卡。它们一块儿处理与电缆(或其余任何传输媒介)的物理接口细节。google
2).网络层,也称做互联网层,处理分组在网络中的活动,例如分组的选路。网络层协议包括IP协议(网际协议)、ICMP协议(Internet互联网控制报文协议),以及IGMP协议(Internet组管理协议)。spa
3).传输层主要是为两台主机上的应用程序提供端到端的通讯。在TCP/IP协议族中,有两个互不相同的传输协议:TCP(传输控制协议)和UDP(用户数据报协议)。TCP为两台主机提供高可靠性的数据通讯。他所做的工做包括把应用程序交给它的数据分红合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时间等。因为传输层提供了高可靠性的端到端通讯,所以应用层能够忽略全部这些细节。而另外一方面,UDP则为应用层提供一种很是简单的服务。它只是把称做数据报的分组从一台主机发送到另外一台主机,但并不保证该数据报能到达另外一端。任何须须的可靠性必须由应用层来提供。操作系统
4).应用层负责处理特定的应用程序细节。包括Telnet(远程登陆)、FTP(文件传输协议)、SMTP(简单邮件传送协议)以及SNMP(简单网络管理协议)等。
二. TCP协议
TCP是一种面向链接(链接导向)的、可靠的基于字节流的传输层通讯协议。TCP将用户数据打包成报文段,它发送后启动一个定时器,另外一端收到的数据进行确认、对失序的数据从新排序、丢弃重复数据。
TCP的特色有:
1. TCP是面向链接的运输层协议
2. 每一条TCP链接只能有两个端点,每一条TCP链接只能是点对点的
3. TCP提供可靠交付的服务
4. TCP提供全双工通讯。数据在两个方向上独立的进行传输。所以,链接的每一端必须保持每一个方向上的传输数据序号。
5. 面向字节流。面向字节流的含义:虽然应用程序和TCP交互是一次一个数据块,但TCP把应用程序交下来的数据仅仅是一连串的无结构的字节流
TCP报文首部,以下图所示:
源端口、目标端口:计算机上的进程要和其余进程通讯是要经过计算机端口的,而一个计算机端口某个时刻只能被一个进程占用,因此经过指定源端口和目标端口,就能够知道是哪两个进程须要通讯。源端口、目标端口是用16位表示的,可推算计算机的端口个数为2^16个。
序列号:表示本报文段所发送数据的第一个字节的编号。在TCP链接中所传送的字节流的每个字节都会按顺序编号。因为序列号由32位表示,因此每2^32个字节,就会出现序列号回绕,再次从 0 开始。那如何区分两个相同序列号的不一样TCP报文段就是一个问题了,后面会有答案,暂时能够无论。
确认号:表示接收方指望收到发送方下一个报文段的第一个字节数据的编号。也就是告诉发送发:我但愿你(指发送方)下次发送的数据的第一个字节数据的编号是这个确认号。也就是告诉发送方:我但愿你(指发送方)下次发送给个人TCP报文段的序列号字段的值是这个确认号。
TCP首部长度:因为TCP首部包含一个长度可变的选项部分,因此须要这么一个值来指定这个TCP报文段到底有多长。或者能够这么理解:就是表示TCP报文段中数据部分在整个TCP报文段中的位置。该字段的单位是32位字,即:4个字节。
URG:表示本报文段中发送的数据是否包含紧急数据。URG=1,表示有紧急数据。后面的紧急指针字段只有当URG=1时才有效。
ACK:表示是否前面的确认号字段是否有效。ACK=1,表示有效。只有当ACK=1时,前面的确认号字段才有效。TCP规定,链接创建后,ACK必须为1。
PSH:告诉对方收到该报文段后是否应该当即把数据推送给上层。若是为1,则表示对方应当当即把数据提交给上层,而不是缓存起来。
RST:只有当RST=1时才有用。若是你收到一个RST=1的报文,说明你与主机的链接出现了严重错误(如主机崩溃),必须释放链接,而后再从新创建链接。或者说明你上次发送给主机的数据有问题,主机拒绝响应。
SYN:在创建链接时使用,用来同步序号。当SYN=1,ACK=0时,表示这是一个请求创建链接的报文段;当SYN=1,ACK=1时,表示对方赞成创建链接。SYN=1,说明这是一个请求创建链接或赞成创建链接的报文。只有在前两次握手中SYN才置为1。
FIN:标记数据是否发送完毕。若是FIN=1,就至关于告诉对方:“个人数据已经发送完毕,你能够释放链接了”
窗口大小:表示如今运行对方发送的数据量。也就是告诉对方,从本报文段的确认号开始容许对方发送的数据量。
校验和:提供额外的可靠性。具体如何校验,参考其余资料。
紧急指针:标记紧急数据在数据字段中的位置。
选项部分:其最大长度可根据TCP首部长度进行推算。TCP首部长度用4位表示,那么选项部分最长为:(2^4-1)*4-20=40字节。
TCP三次握手过程
第一次握手:创建链接时,客户端发送同步序号syn=1,随机产生seq number数据包发送(seq=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到报文请求,由SYN=1知道客户端要创建链接请求,向客户端发送ack number(ack=x+1),syn=1,同时本身也发送一个SYN包(seq=y),即SYN+ACK包,此时服务器进入SYN_RCVD
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ack(ack=y+1),同时发送序号seq=y+1,此包发送完毕,客户端和服务器进入ESTABLISHED(TCP链接成功)状态,完成三次握手。
TCP三次握手过程以下图所示:
四次断开:
因为TCP链接是全双工的,所以每一个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的链接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP链接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另外一方执行被动关闭。
(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN同样,一个FIN将占用一个序号。
(3)服务器B关闭与客户端A的链接,发送一个FIN给客户端A。
(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
TCP采用四次挥手关闭链接如图所示。
三次握手状态详细说明:
1.CLOSED:起始点,在超时或者链接关闭时候进入此状态。
2.LISTEN:服务端在等待链接过来时候的状态,服务端为此要调用socket,bind,listen函数,就能进入此状态。此称为应用程序被动打开(等待客户端来链接)。
3.SYN_SENT:客户端发起链接,发送SYN给服务器端。若是服务器端不能链接,则直接进入CLOSED状态。
4.SYN_RCVD:跟3对应,服务器端接受客户端的SYN请求,服务器端由LISTEN状态进入SYN_RCVD状态。同时服务器端要回应一个ACK,同时发送一个SYN给客户端;另一种状况,客户端在发起SYN的同时接收到服务器端得SYN请求,客户端就会由SYN_SENT到SYN_RCVD状态。
5.ESTABLISHED:服务器端和客户端在完成3次握手进入状态,说明已经能够开始传输数据了。
四次断开状态详细说明:
6.FIN_WAIT_1: 关闭的一方,由ESTABLISHED进入此状态。具体的动做是发送FIN给对方。
7.FIN_WAIT_2: 闭的一方,接收到对方的FIN_ACK(即fin包的回应包,进入此状态。
8.CLOSE_WAIT: 接收到FIN之后,被动关闭的一方进入此状态。具体动做是接收到FIN,同时发送ack。(之因此叫close_wait能够理解为被动关闭方此时正在等待上层应用发出关闭链接指令)
9.LAST_ACK:被动关闭的一方,发起关闭请求,由状态close_wait进入此状态。具体动做是发送FIN给对方,同时在接收到ACK进入CLOSED状态。
10.CLOSING:两边同时发起关闭请求,会由FIN_WAIT_1进入此状态。具体动做是接收到FIN请求,同时相应一个ACK。
11.TIME_WAIT:最纠结的状态来了。从状态图上能够看出,有三个状态能够转化成它:
a:由FIN_WAIT_2进入此状态:在双方不一样时发起FIN的状况下,主动关闭的一方在完成自身发起的关闭请求后,接收到被动关闭一方的FIN后进入的状态。
b:由CLOSING状态进入:双方同时发起关闭,都作了发起FIN的请求,同时接收到了FIN并作了ACK的状况下,有CLOSING状态进入。
c:由FIN_WAIT_1状态进入:同时接收到FIN(对方发起),ACK(自己发起的FIN回应),与b的区别在于自己发起的FIN回应的ACK先于对方的FIN请求到达,而b是FIN先到达。这种状况几率最小。
关闭的4次链接最难理解的状态是TIME_WAIT,存在TIME_WAIT的2个理由:
1.可靠地实现TCP全双工链接的终止。
2.容许老的重复分节在网络中消逝。
问题:TCP创建链接时,为何是 三次握手呢?
client发出的第一个链接请求报文段并无丢失,而是在某个网络结点长时间的滞留了,以至延误到链接释放之后的某个时间才到达server。原本这是一个早已失效的报文段。但server收到此失效的链接请求报文段后,就误认为是client再次发出的一个新的链接请求。因而就向client发出确认报文段,赞成创建链接。假设不采用“三次握手”,那么只要server发出确认,新的链接就创建了。因为如今client并无发出创建链接的请求,所以不会理睬server的确认,也不会向server发送数据。但server却觉得新的运输链接已经创建,并一直等待client发来数据。这样,server的不少资源就白白浪费掉了。采用“三次握手”的办法能够防止上述现象发生。例如刚才那种状况,client不会向server的确认发出确认。server因为收不到确认,就知道client并无要求创建链接。”在google上搜到的网友的解释:
这个问题的本质是, 信道不可靠, 可是通讯双发须要就某个问题达成一致. 而要解决这个问题, 不管你在消息中包含什么信息, 三次通讯是理论上的最小值. 因此三次握手不是TCP自己的要求, 而是为了知足"在不可靠信道上可靠地传输信息"这一需求所致使的. 请注意这里的本质需求,信道不可靠, 数据传输要可靠. 三次达到了, 那后面你想接着握手也好, 发数据也好, 跟进行可靠信息传输的需求就不要紧了. 所以,若是信道是可靠的, 即不管何时发出消息, 对方必定能收到, 或者你不关心是否要保证对方收到你的消息, 那就能像UDP那样直接发送消息就能够了.”
为何创建链接协议是三次握手,而关闭链接倒是四次握手呢?
这是由于服务端的LISTEN状态下的SOCKET当收到SYN报文的建连请求后,它能够把ACK和SYN(ACK起应答做用,而SYN起同步做用)放在一个报文里来发送。但关闭链接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了;但未必你全部的数据都所有发送给对方了,因此你可能未必会立刻会关闭SOCKET,也即你可能还须要发送一些数据给对方以后,再发送FIN报文给对方来表示你赞成如今能够关闭链接了,因此它这里的ACK报文和FIN报文多数状况下都是分开发送的。
为何TIME_WAIT状态还须要等2MSL后才能返回到CLOSED状态?
这是由于:虽然双方都赞成关闭链接了,并且握手的4个报文也都协调和发送完毕,按理能够直接回到CLOSED状态(就比如从SYN_SEND状态到 ESTABLISH状态那样);可是由于咱们必需要假想网络是不可靠的,你没法保证你最后发送的ACK报文会必定被对方收到,所以对方处于 LAST_ACK状态下的SOCKET可能会由于超时未收到ACK报文,而重发FIN报文,因此这个TIME_WAIT状态的做用就是用来重发可能丢失的 ACK报文。