Tcp 协议
相关术语
- 全双工:
全双工(Full Duplex)是通讯传输的一个术语。通信允许数据在两个方向上同时传输,它在能力上相当于两个单工通信方式的结合。全双工指可以同时(瞬时)进行信号的双向传输(A→B且B→A)。指A→B的同时B→A,是瞬时同步的。
- 半双工:
半双工(Half Duplex),所谓半双工就是指一个时间段内只有一个动作发生,举个简单例子,一条窄窄的马路,同时只能有一辆车通过,当目前有两辆车对开,这种情况下就只能一辆先过,等到头儿后另一辆再开,这个例子就形象的说明了半双工的原理。早期的对讲机、以及早期集线器等设备都是基于半双工的产品。随着技术的不断进步,半双工会逐渐退出历史舞台。
- 单工:
单工就是在只允许甲方向乙方传送信息,而乙方不能向甲方传送 。(比喻汽车的单行道。)
- MSL:
Max segment lifetime ,报文最大生存时间,是指任何报文在网络上存在的最长时间,超过这个时间报文将会被丢弃。 在Linux 系统中,MSL 被定义成30 秒, 2MSL 就是60 秒。
相关基本了解
数据在网络中的传输,数据从打包到发送到对应的目标地址,会经过一系列的处理最后生成一个个可以在网络中传输的数据包。每个过程对数据进行相应的处理,我们普遍将这些过程分为5个层级模型来对每层对数据所做的处理(有些会将此过程分为7层模型此处我们只分析5层模型的情况)
七层协议中,应用层又细分:应用层、
网络层级模型及协议
由App接受数据开始自下向上分5层为:
- 实体层
- 实体层作用:实体层就是把电脑链接提来的物理手段。主要规定了网络的一些电气特性,负责传输0和1的电信号
- 链路层
- 链路层作用:单纯的0/1电信号没有任何意义,必须规定解读方式:多少个电信号为一组?组里的每个信号位有和意义?链接层的作用就是在实体层上方规定了0和1的分组方式
- 对应的协议:以太网协议
- 网络层
- 网络层的作用:是引进一套新的地址,使得我们能够区分不同的计算机是否属于同一个子网络。这套地址就叫做"网络地址",简称"网址"。
- 对应的协议:IP协议、AIP协议
- 传输层
- 传输层的作用:就是建立"端口到端口"的通信。相比之下,"网络层"的功能是建立"主机到主机"的通信。只要确定主机和端口,我们就能实现程序之间的交流。因此,Unix系统就把主机+端口,叫做"套接字"(socket)。有了它,就可以进行网络应用程序开发了。
- 对应的协议:TCP协议、UDP协议
- 应用层
- 应用层的作用:主要是规定了数据传输的格式,
- 对应的协议:http、https、dns、ftp...
由上可知,不同的协议会作用在不同的层级规定了不同的数据处理方式。
TCP协议链接过程
上面可以TCP协议是作用在传输层的协议,主要是在数据传输时,建立出发端口到目标端口的链接。其建立链接的过程如下所示:
三次握手
所谓三次握手(Three-Way Handshake)即建立TCP连接,就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包以确认连接的建立。在socket编程中,这一过程由客户端执行connect来触发,整个流程如下图所示:
- 第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
- 第二次握手:Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
- 第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。
四次挥手
所谓四次挥手(Four-Way Wavehand)即终止TCP连接,就是指断开一个TCP连接时,需要客户端和服务端总共发送4个包以确认连接的断开。在socket编程中,这一过程由客户端或服务端任一方执行close来触发,整个流程如下图所示:
由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭,上图描述的即是如此。
- 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
- 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
- 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
- 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。(此时server收到消息后会立即关闭,client会等待2MSL后关闭)
TCP协议中先关字段及其作用
-
TCP报文格式
-
相关字段作用
- 源端口,16bits,范围0~65525。
- 目的端口,16bits,范围同上。
- sequence number: 数据序号,32bits,TCP 连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号。
- acknoledgement number: 确认号,32bits,期望收到对方的下一个报文段的数据的第一个字节的序号。
- 数据偏移,4bits,单位为4字节,它指出报文数据距TCP报头的起始处有多远(TCP报文头长度)。
- 保留字段6bits,保留今后使用,目前置0处理。
- URG:紧急比特,1bit,当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)
- ACK:确认比特,1bit,只有当ACK=1时确认号字段才有效。当ACK=0时,确认号无效
- PSH:推送比特,1bit,接收方TCP收到推送比特置1的报文段,就尽快地交付给接收应用进程,而不再等到整个缓存都填满了后再向上交付
- RST:复位比特,1bit,当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接
- SYN:同步比特,1bit,同步比特SYN置为1,就表示这是一个连接请求或连接接受报文
- FIN:终止比特,1bit,用来释放一个连接。当FIN=1时,表明此报文段的发送端的数据已发送完毕,并要求释放运输连接
- 窗口大小,16bits,窗口字段用来控制对方发送的数据量,单位为字节。TCP 连接的一端根据设置的缓存空间大小确定自己的接收窗口大小,然后通知对方以确定对方的发送窗口的上限。
- 检验和,16bits,检验和字段检验的范围包括首部和数据这两部分。在计算检验和时,要在TCP 报文段的前面加上12 字节的伪首部。
- 紧急指针字段,16bits,紧急指针指出在本报文段中的紧急数据的最后一个字节的序号。
- 选项字段,长度可变。TCP首部可以有多达40字节的可选信息,用于把附加信息传递给终点,或用来对齐其它选项。这部分最多包含40字节,因为TCP头部最长是60字节(其中还包含前面讨论的20字节的固定部分) 选项的第一个字段kind说明选项的类型。有的TCP选项没有后面两个字段,仅包含1字节的kind字段。第二个字段length(如果有的话)指定该选项的总长度,该长度包括kind字段和length字段占据的2字节。第三个字段info(如果有的话)是选项的具体信息. kind=0是选项表结束选项 kind=1是空操作(nop)选项,没有特殊含义,一般用于将TCP选项的总长度填充为4字节的整数倍 kind=2是最大报文段长度选项,TCP连接初始化时,通信双方使用该选项来协商最大报文段长度(Max Segment Size,MSS)。TCP模块通常将MSS设置为(MTU-40)字节(减掉的这40字节包括20字节的TCP头部和20字节的IP头部)。这样携带TCP报文段的IP数据报的长度就不会超过MTU(假设TCP头部和IP头部都不包含选项字段,并且这也是一般情况),从而避免本机发生IP分片。对以太网而言,MSS值是1460(1500-40)字节。
讨论
- TCP客户端发起连接时为什么需要第三次确认呢 ?
主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。 如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。
如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。
- 在四次挥手之后客户端为什么最后还要等待2MSL?
主要保证服务器能够够到最后一次报文,保证此次发送的报文在网络中彻底消失
- 第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。
- 第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。
- 为什么建立连接是三次握手而关闭连接确是四次挥手呢?
因为TCP数据传输是全双工的,client 和 server 可以同时互相发送数据,当其中一方收到FIN时,可能同时在向另一方发送数据,因此需要双方同时确认彼此都没有数据需要发送才能断开连接,因此需要四次挥手确认。而在发起连接是相当于半双工的,只有等待一方响应才会处理发送下一个阶段的数据,所以只需要三次握手。