飞道的博客

TCP协议详解

404人阅读  评论(0)

目录

一、认识传输层

二、清楚了传输层,我们来看一下它提供的TCP协议。

1、通过序号和确认序号提高可靠性

什么是序列号?

重发超时如何确定?

以上功能有一个名称叫做滑动窗口机制。

窗口控制与重发控制

流控制:

拥塞控制:

2、tcp的面向连接:

tcp的协议格式:

详解TCP三次握手和四次挥手:

总结:


一、认识传输层

TCP协议工作在传输层,是与UDP协议齐名的传输控制协议,让我们一起来了解她的前生今世。

首先讲一下传输层是什么东西。

传输层位于TCP/IP五层协议模型中,应用层和网络层之家,应用层就是我们能用真切看到的一些应用程序,随着互联网的出现,计算机之间可以使用它进行沟通了,那么问题来了,不同计算机之间怎么沟通成了一个急需解决的问题,ISO提出了七层通信模型,但是由于太复杂被弃用,现在被人们广泛使用的是TCP/IP五层协议模型。一次通信就像是一次寄快递的过程,包裹上必须有,发信人地址,电话,收信人地址电话,在网络通信中还加了一层关系那就是传输协议,就比如你用的是特快还是普通快递。说白了,就是决定这一次通信的传输方式的。

二、清楚了传输层,我们来看一下它提供的TCP协议。

总的来说TCP协议是:面向连接、可靠传输提供字节流服务。那么他到底是怎么样实现功能的呢?

1、通过序号和确认序号提高可靠性

就像我们平时打电话一样,对方说一句话呢你嗯一下,对方就知道你听见了,要是很久没有回应,对方就要重新说这句话啦,在计算机的世界,所有的东西都使用数字来表示,包括两个计算机之间“通电话”。

如上图所示,确认应答就是告诉对方,之前的数据我收到了,发以我说的序号开始的数据吧。

但是上面这种完美的场景在网络通信中是不现实的,伴随着网络延时,以及其他各种网络问题,会产生比如接收端收不到数据,接收端就会在特定的时间段以后重发确认应答数,当然如果确认应答不能够迅速到达,发送端会在特定的时间段之后重发之前的数据,这就会造成流量资源的浪费。要解决上面出现的问题,智慧的工程师们想出了很多基于序列号的解决方案。

什么是序列号?

序列号是按顺序给要发送的数据按每一个字节(八位一个字节)编号,接收端查询接收数据TCP首部中的序列号和数据的长度,将自己下一步应该接收的序号作为确认应答返送回去,这样子通过序列号和确认应答号,TCP可以实现可靠传输。

重发超时如何确定?

在BSD的Unix和Windows系统中,超时时间都是以0.5秒为单位进行控制,因此超时等待时间都是0.5秒的整数倍,最初数据包还不知道往返时间,因此超时重发时间都在6秒左右。

数据被重发之后若还收不到确认应答,则进行再次发送,此时,等待确认应答的时间将会以2被或者4倍的指数函数延长。达到一定的重发次数之后,仍然没有应答,就会认为网络或者对端主机发生异常,强制关闭连接,通知应用程序通信异常。

有了序号之后,TCP可以通过窗口控制提高速度

一次发送一次应答的方式显然不够迅速,为了解决这个问题,TCP引入了窗口的概念,即使在应答时间较短的情况下,他也能控制网络性能的下降。应答不再是每一个分段,而是以更大的单位进行确认,发送端发送一个段之后不需要等待应答,而是继续发送。

窗口的大小就是无需等待应答而可以继续发送数据的最大值,实现这个机制使用了大量的缓冲区,实现对多个段同时进行应答的功能。(窗口的大小是在三次握手的时候协商MSS(最大报文长度)窗口的大小取决于接收方接收缓冲区剩余空间的大小)

以上功能有一个名称叫做滑动窗口机制。

如上图就是一次窗口滑动的过程,在收到在窗口内部数据的确认应答序号之后,窗口就会向前滑动至收到的确认应答处,缓冲区之前的数据就可以被清除,接收端窗口之前已经收到的数据 就可以被操作系统读取。

接下里分析一下窗口前后沿滑动的情况。

发送方维护一个窗口前沿和后沿,和一个当前发送位置的指针来维护一个窗口。

接收方根据接收缓冲区剩余空间的大小决定窗口的前后沿。

    a、发送方前沿移动:取决于接收到的窗口大小

    b、发送方后沿的移动:取决于接收到得确认应答号。

    c、接收方前沿的移动:缓冲区剩余空间的大小

    d、接收方后沿的移动:是否收到后沿的数据。

当后沿到了前沿:

对于发送方:窗口为0,并且发出去的数据都收到了确认应答。

对于发送方:接收缓冲区已满。

接收方收到了第二条数据但是没有收到一条数据:

接收方后沿不会移动,因为后沿标志着前面已经确认收到的数据。

窗口控制与重发控制

在使用窗口的过程中,如果出现了丢失怎么办?

如果发送端的数据丢失,接收端就会重复发送同一个确认应答序号,当接收端收到三次相同的确认应答就会认为,此段数据丢失,重发这段数据。

如果接收端的确认应答数据丢失,如果一个小的序列号丢失了,但是收到了大的序列号,就会认为大的序列号之前的所有数据都被收到,要是什么确认应答都收不到,则会重发窗口内的数据,这里面可能会涉及到拥塞控制:发送方维护一个拥塞窗口,以慢启动快增长的形式发送数据。

连续三次收到同一个确认应答发送数据也叫快速重传服务

流控制:

发送方相对而言是一个比较轻松的活,接收方接收端接收到数据之后会进行处理,或者接收端干的不止接收数据一件事情,有时出现接收端不能接受数据的情况,那么流量就会被浪费,因此,在确认应答包里,会有一个给发送端设定窗口大小的字段,通过发送方的窗口大小决定发送端的发送快慢。

拥塞控制:

计算机网络都处在一个共享的环境,因此也有可能因为其他主机之间的通信使得网络拥堵,出现网络拥堵时极有可能因为出现一个较大量的数据而是网络瘫痪。

tcp为了防止这种情况,在通信一开始就会通过个叫做慢启动的算得出的数值,对发送数据量进行控制。

2、tcp的面向连接:

tcp通过三次握手建立连接,四次挥手断开连接,我们来详细看一下,

tcp的协议格式:

  • 数据偏移:这个子段表明tcp所传输的数据应该是从哪个部分开始计算的,如果没有选项数据的话,一般是5 单位字节,表示从TCP包0的位置偏移5个字节的数据,就是TCP传输的数据。
  • 控制位:
  • CWR:与后面ECE都用于IP首部的ECN字段,ECE标志为1 时,则通知对方已将拥塞窗口缩小
  • ECE:置位1会通知通信对方,从对方这边到这边的网络有拥塞,在收到数据包的IP首部中ECN为1时将TCP首部中的ECE置位1
  • URG:为1 时表示有紧急数据要处理。
  • ACK:为1时,表示确认应答子段有效,TCP规定除了建立连接时的SYN包之外,其他的必须置为1
  • PSH:为1时,需要将收到的数据立即传给上层协议,为0时,数据先进入缓存
  • RST:为1时,TCP连接有异常,必须强制断开连接
  • SYN:用于建立连接,为1时表示希望建立连接,
  • FIN:为1时,表示不再有数据发送,希望断开连接,但是只表示没有数据发送,不表示不接受数据,也不表示立即断开连接。

窗口大小:

用于发送方向接收方,发送窗口大小,或者接收方发送窗口探测包。

TCP和UDP的校验相似,区别在于TCP的校验和无法关闭。

详解TCP三次握手和四次挥手:

TCP是有状态的连接管理,如图所示:

客户端socket在建立连接时,向服务端发送SYN(syn=j)请求,此时状态为STN_SEND,等待服务器接收,

服务器收到之后,发送连接请求SYN+ACK(syn=k,ack=j+1),状态为SYN_RECV

客户端收到后,发送ACK(ack=k+1),状态为ESTABLISHED,收到ACK后服务端状态也设为ESTABLISHED。

为什么是三次握手不是四次或者两次?一次可靠的通信必须满足一下关系。

cli srv
自己能发送数据       第一次握手 自己能发送数据      第二次握手
对方能发送数据      第二次握手 对方能发送数据      第二次握手
自己能接收数据      第二次握手 自己能接收数据       第二次握手
对方能接收数据      第二次握手 对方能接收数据

可以看到两次握手,服务端不知道对方到底能不能接收数据,所以还需要三次握手,对方给应答,三次能完成的事,为什么要四次呢。

四次挥手断开连接,从三次握手建立连接看到,三次握手就可以建立可靠的通信,为什么断开要四次呢?

考虑如果三次,那么就将ACK和FIN和在一起发送,这样会出现一系列的问题,FIN包表示我想关闭连接,而且只是关闭写端表示不再发送数据,如果服务端收到FIN就回应FIN和ACK,如果数据没有完全接收完,就让发送端关闭,这是不合理的。

应该在服务端确认不再需要接收数据,即自己不再读数据了,才能给发送端发送FIN包。所以是四次,其实这是常理问题,不属于技术问题。^_^

断开连接的过程图里面表述的很清楚不再赘述了,提几个问题吧?

a、FIN包发送方为什么在接收最后一个ACK,没有立即断开连接进入SLOSED状态,而是进入TIME_WAIT等待2个MSL?

1、立即进入CLOSED可能会带来危险,如果这个ACK包丢了,对方过了超时等待时间,重新发送FIN包,此时如果系统以相同的地址重新建立连接,突然收到FIN包是不合理的,或者新连接的SYN给对方后,对方正处在LSAT_ACK,收到SYN会 认为连接出错,会发送RST重新建立连接。因此主动关闭方要等待2个MSL处理可能重传的FIN包。

等待2个MSL是要将本次连接的所有数据都消失在网络中。

b、三次握手失败了怎么办?

1、SYN没有到达,此时对srv是没有影响的

2、srv发送了SYN和ACK但是收不到ACK,等待超时后,释放当前这个套接字,发送RST重新建立连接。

c、服务端出现大量的CLOSE_WAIT是什么原因?

在ACK确认之后,等待程序调用close或者shutdown(SHUT_WR),以便发送FIN包,这属于程序上的漏洞,没有释放资源。

d、服务器上出现大量TIME_WAIT?

这个状态出现在发送完最后一个ACK之后,由于服务器大量主动的关闭连接,解决方案:设置MSL时长短一点。

总结:

可靠传输

    实现机制:面向连接、确认应答、超时重传、序号与确认序号、 校验和

    避免丢包

        发送过快:滑动窗口机制:通过窗口大小子段,实现滑动窗口机制,进行流量控制。

        网络不好:拥塞控制:发送方维护一个拥塞窗口,以慢启动块增长的形式发送数据。

    提高性能

        快速重传、捎带应答、延时应答    

字节流传输的缺点:粘包->解决方案:特殊字符、数据定长、应用层头部中定义数据长度

 


转载:https://blog.csdn.net/weixin_43447989/article/details/106874590
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场