tcp协议 [1]

最主要的特点:

1.TCP是面向连接的运输层协议
  应用程序在使用TCP协议之前,必须先建立TCP连接
  在传送数据完毕后,必须释放已经建立的TCP连接
2.每一条TCP连接只能有两个端点,只能是点对点的
3.TCP提供可靠交付的服务
  TCP连接传送的数据保证无差错、不丢失、不重复、并按序到达
4.TCP提供全双工通信
  TCP允许通信双方的应用进程在任何时候都能发送数据
  TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据
5.面向字节流
../../../_images/tcp_protocol1.png
../../../_images/tcp_protocol2.png

TCP报文首部固定部分各字段的意义如下:

1.源端口和目的端口
  各占两字节,分别写入源端口号和目的端口号
  TCP的复用也是通过端口实现的
2.报文段序号
  占4字节
  在一个TCP连接中传送的字节流中的每一个字节都按顺序编号
  整个要传送的字节流的起始序号必须在连接建立时设置
  首部中的序号字段值则是指本报文所发送的数据的第一个字节的序号
3.确认号
  期望收到对方下一个报文段的第一个数据字节的序号
  若确认号为N,则表明到序号N-1为止的所有数据都已正确收到
4.数据偏移
  指出TCP报文段的数据起始处距离TCP报文段的起始处有多远
  实际上指出了TCP报文段的首部长度
5.保留
保留为今后使用,目前应置为0
6.6个控制位
  紧急URG:当URG为1时,表明紧急指针字段有效,告诉系统有紧急数据,应尽快优先传送。
  确认ACK:TCP规定,在连接建立后所有传送的报文段都必须把ACK置1
  推送PSH,很少使用
  复位RST:当RST=1时,表明TCP连接中出现严重错误,必须释放连接,然后再重新建立运输连接
  同步SYN:在连接建立时用来同步序号
    当SYN=1而ACK=0时,表明这是一个连接请求报文段
    对方若同意建立连接,则应在响应的报文段中使用SYN=1和ACK=1
  终止FIN:用来释放一个连接
    当FIN=1时,表明此报文段的发送方的数据已发送完毕,并要求释放运输连接
7.窗口
  窗口字段明确指出了现在允许对方发送的数据量,该值经常在动态变化着
  例如:
  确认号是701,窗口字段是1000
  这就表明从701算起,发送此报文段的一方还有接收1000个字节数据的接收缓存空间
8.检验和
  检验和字段检验的范围包括首部和数据这两部分
  和UDP一样,在计算检验和时要在TCP报文段的前面加上12字节的伪首部
9.紧急指针
  紧急指针仅在URG=1时才有意义,它指出本报文段中的紧急数据的字节数
  **即使窗口为零时也可发送紧急数据
10.选项
  可选
  选项有最大报文长度MSS、窗口扩大选项、时间戳选项、选择确认选项等
../../../_images/tcp_protocol3.png

TCP可靠传输的实现:

% 为方便描述,假定数据传输只在一个方向上进行,即A发送数据,B给出确认
TCP的滑动窗口是以字节为单位的.
假定A收到B发来的确认报文字段,其中窗口是20字节,而确认号是31字节
表明:B期望接收到的下一个序号是31,序号30之前的数据已经收到了
A的发送窗口的位置由B发来的确认报文中的确认号和窗口大小确定
../../../_images/tcp_protocol4.png

继续:

现在假定A发送了序号为31-41的数据
从上图图中可以看出要描述一个发送窗口的状态需要三个指针P1,P2,P3
小于P1的是已发送并收到确认的部分
大于P3的是不允许发送部分

B的接收窗口大小为20
在接收窗口外面,到30号为止的数据均发送过确认并交付主机使用,因此B不再保留(之前的数据)
假设B收到了32和33的数据,却没收到31的数据(并不保证按序到达)
因此B的发送的确认号仍然是31,而不能是32或33
../../../_images/tcp_protocol5.png

继续:

现假定B收到序号为31的数据并把序号为31-33的数据交付给主机,并删除这些数据
接着把接收窗口向前移动3个序号,同时给A发出确认
其窗口值仍为20,但确认号为34,表明B已经接收到序号33为止的数据
而B收到的37、38和40的数据,但没按序到达,只能先暂存在接收窗口中
A收到B的确认后,将发送窗口向前滑动3个序号,但指针P2不动
A继续发送完序号42-53的数据后,指针P2向前与P3重合
发送窗内的数据以发送完,但还没收到确认,因此必须停止发送
../../../_images/tcp_protocol6.png

发送缓存用来暂时存放:

发送应用程序传送给发送方TCP准备的数据,TCP已发送但尚未收到确认的数据
发送窗口通常只是发送缓存的一部分,已被确认的数据应当从发送缓存中删除,
因此发送缓存与发送窗口的后沿是重合的
发送应用程序必须控制写入缓存的速率,不能太快,否则发送缓存就会没有存放数据的空间

接收缓存用来暂时存放:

按序到达的,但尚未被接收应用程序读取的数据、未按序到达的数据
如果收到的分组检测出有差错,则要丢弃
如果接收应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减小到0
反之,接收应用程序能够及时从接收缓存中读取收到数据,接收窗口就会变大,但最大也不能超过接收缓存的大小

超时重传机制:

TCP每发送一个报文段,就对这个报文段设置一次计时器
只要达到计时器设置的重传时间还没有收到确认,就要重传这个报文段
由于数据链路层和运输层的往返实验概率分布存在很大差异,因此有必要选择合适的超时重传时间

TCP采用了一中自适应算法来确定超时重传时间
它记录一个报文段发出的时间,以及收到相应的确认的时间
这两个时间差就是报文段的往返时间RTT
TCP保留了RTT的一个加权平均往返时间RTTs
RTTs的计算方法如下,推荐的阿尔法值为1/8:
  新的RTTs = (1-a) * (旧的RTTs) +a*(新的RTTs样本)
显然超时重传时间RTO应略大于RTTs:
  RTO = RTTs + 4* RTTd
% RTTd是TTT的偏差的加权平均值
../../../_images/tcp_protocol7.png

选择确认SACK:

若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据
采用选择确认的方法来传送缺少的数据,而不重传已经正确接收到的数据
用一个例子来说明(Selctive ACK)工作原理
如上图所示,接收放收到了前面的字节流不连续的两个字节块
如果这些字节的序号都在接收窗口内,那么接收方就先收下这些数据
但要把这些信息准确的告诉发送放,使发送方不要在重复发送这些已经收到的数据

TCP首部没有哪个字段能够提供上述这些字节块的边界信息
如果要使用选择确认,那么在建立TCP连接时,就要在TCP首部的选项上加上“允许SACK”的选项

TCP的流量控制与拥塞控制:

1.流量控制:
所谓的流量控制就是让发送方的发送速率不要太快,让接收方来得及接受
利用滑动窗口机制可以很方便的在TCP连接上实现对发送方的流量控制
2.拥塞控制:
某段时间,对网络中的某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变化,这种情况叫做拥塞
网络拥塞往往是由许多因素引起,简单的提高节点处理机的速度或者扩大结点缓存的存储空间并不能解决拥塞问题
问题的是指往往是整个系统的各个部分不匹配,只有各个部分平衡了,问题才会得到解决

拥塞控制和流量控制的差别:

所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载
拥塞控制所要做的都有一个前提,就是网络能承受现有的网络负荷

流量控制往往指的是点对点通信量的控制,是个端到端的问题
流量控制所要做的就是控制发送端发送数据的速率,以便使接收端来得及接受

拥塞控制是很难设计的,因为它是一个动态的问题
许多情况下,甚至就是拥塞控制机制本身成为引起网络性能恶化甚至死锁的原因
RFC定义了进行拥塞控制的四种算法:慢开始、拥塞避免、快重传和快恢复
../../../_images/tcp_protocol8.png

TCP的建立:

如上图,可以简单的称为三次握手:
首先,客户端向服务器申请打开某一个端口(用SYN段等于1的TCP报文)
然后,服务器端发回一个ACK报文通知客户端请求报文收到
客户端收到确认报文以后再次发出确认报文,确认刚才服务器端发出的确认报文

如果再加上TCP的超时重传机制,那么TCP就完全可以保证一个数据包被送到目的地
../../../_images/tcp_protocol9.png

TCP的终止:

建立一个连接需要三次握手,而终止一个连接要经过4次握手,这是由TCP的半关闭(half close)造成的
既然一个 TCP连接是全双工(即数据在两个方向上能同时传递),因此每个方向必须单独地进行关闭
这原则就是当一方完成它的数据发送任务后就能发送一个 FIN来终止这个方向连接
当一端收到一个 FIN,它必须通知应用层另一端几经终止了那个方向的数据传送

客户机给服务器一个FIN为1的TCP报文,然后服务器返回给客户端一个确认ACK报文
并且发送一个FIN报文,当客户机回复ACK报文后(四次握手),连接就结束了

TCP的状态变迁图:

../../../_images/tcp_protocol10.png
../../../_images/tcp_ip_ios_osi.gif
[1]https://www.jianshu.com/p/43a25804b2e8