zoukankan      html  css  js  c++  java
  • TCP协议

    一、TCP报头

    二、连接管理机制

    三次握手

    1、TCP服务器进程先创建传输控制块TCB,此时服务器就进入了 LISTEN(监听)状态
    2、TCP客户端进程也是先创建传输控制块TCB, 然后向服务器发出连接请求报文,此时报文首部中的同步标志位SYN=1, 同时选择一个初始序列号 seq = x, 此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。
    3、TCP服务器收到请求报文后, 如果同意连接, 则发出确认报文。确认报文中的 ACK=1, SYN=1, 确认序号是 x+1, 同时也要为自己初始化一个序列号 seq = y, 此时, TCP服务器进程进入了SYN-RCVD(同步收到)状态。
    4、TCP客户端进程收到确认后还, 要向服务器给出确认。确认报文的ACK=1,确认序号是 y+1,自己的序列号是 x+1.
    5、此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

    四次挥手

    1、客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u,此时客户端进入FIN-WAIT-1(终止等待1)状态。
    2、服务器收到连接释放报文,发出确认报文,ACK=1,确认序号为 u+1,并且带上自己的序列号seq=v,此时服务端就进入了CLOSE-WAIT(关闭等待)状态。
    3、客户端收到服务器的确认请求后,此时客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最终数据)
    4、服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,确认序号为v+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
    5、客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,确认序号为w+1,而自己的序列号是u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
    6、服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。

    三、确认应答(ACK机制)

    TCP将每个字节的数据都进行了编号,即为序列号。每一个ACK都带有对应的确认序列号,意思是告诉发送者,我已经收到了哪些数据,下一次你要从哪里开始发。

    四、超时重传

    主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B。如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发。

    但是主机A没收到确认应答也可能是ACK丢失了,这种情况下,主机B会收到很多重复数据。去重的方式是利用序列号判断哪些是重复的数据。

    最大超时时间的动态计算:

    超时以500ms为一个单位进行控制,每次判定超时重发的超时时间都是500ms的整数倍。如果重发一次之后,仍然得不到应答,等待 2*500ms 后再进行重传。如果仍然得不到应答,等待 4*500ms 进行重传。依次类推, 以指数形式递增。累计到一定的重传次数,TCP认为网络异常或者对端主机出现异常,强制关闭连接。

    五、滑动窗口

    目的:为了解决确认应答机制性能差的缺点

    窗口大小指的是无需等待确认应答就可以继续发送数据的最大值.。

    发送前四个段的时候,不需要等待任何ACK,直接发送 。收到第一个ACK确认应答后,窗口向后移动,继续发送第五六七八段的数据。操作系统内核为了维护这个滑动窗口,需要开辟发送缓冲区来记录当前还有哪些数据没有应答,只有ACK确认应答过的数据, 才能从缓冲区删掉。

    出现丢包,需要进行重传

    1、 数据包已经收到,但确认应答ACK丢了。

    这种情况下,部分ACK丢失并无大碍,因为还可以通过后续的ACK来确认对方已经收到了哪些数据包。

    2、数据包丢失

    当某一段报文丢失之后,发送端会一直收到 1001 这样的ACK。如果发送端主机连续三次收到了同样一个 “1001” 这样的应答,就会将对应的数据 1001 - 2000 重新发送 。这个时候接收端收到了 1001 之后,再次返回的ACK就是7001了。因为2001 - 7000接收端其实之前就已经收到了,被放到了接收端操作系统内核的接收缓冲区中。

    六、流量控制

    接收端处理数据的速度是有限的,如果发送端发的太快,导致接收端的缓冲区被填满,这个时候如果发送端继续发送,就会造成丢包,进而引起丢包重传等一系列连锁反应。
    因此TCP支持根据接收端的处理能力,来决定发送端的发送速度。

    接收端将自己可以接收的缓冲区大小放入TCP首部中的 “窗口大小” 字段,通过ACK通知发送端。窗口大小越大,说明网络的吞吐量越高。接收端一旦发现自己的缓冲区快满了,就会将窗口大小设置成一个更小的值通知给发送端。发送端接受到这个窗口大小的通知之后,就会减慢自己的发送速度。如果接收端缓冲区满了,就会将窗口置为0,这时发送方不再发送数据,但是需要定期发送一个窗口探测数据段,让接收端把窗口大小再告诉发送端。

    七、拥塞控制

    滑动窗口能够保证高效可靠地发送大量数据,但是如果当前的网络状态比较拥堵,在刚开始就发送大量的数据,可能引发一些问题。因此,TCP引入慢启动机制,先发少量的数据,摸清当前的网络拥堵状态以后,再决定按照多大的速度传输数据。

    拥塞窗口

    发送开始的时候,定义拥塞窗口大小为1;

    每次收到一个ACK应答,拥塞窗口加1;

    每次发送数据包的时候,将拥塞窗口和接收端主机反馈的窗口大小做比较,取较小的值作为实际发送的窗口。

    像上面这样的拥塞窗口增长速度,是指数级别的。“慢启动” 只是指初始时慢,但是增长速度非常快。为了不增长得那么快, 此处引入慢启动的阈值,当拥塞窗口的大小超过这个阈值的时候,不再按照指数方式增长,而是按照线性方式增长。

    当TCP开始启动的时候,慢启动阈值等于窗口最大值。在每次超时重发的时候,慢启动阈值会变成原来的一半,同时拥塞窗口置回1。

    少量的丢包, 我们仅仅是触发超时重传;大量的丢包,我们就认为是网络拥塞。当TCP通信开始后,网络吞吐量会逐渐上升。随着网络发生拥堵,吞吐量会立刻下降。

    拥塞控制,归根结底是TCP协议想尽可能快的把数据传输给对方,但是又要避免给网络造成太大压力的折中方案。

    八、TCP与UDP的对比

    1、TCP是面向连接的,UDP是无连接

    2、TCP是可靠传输,UDP是不可靠

    3、TCP是点对点连接,UDP可以一对多

    4、TCP面向字节流,UDP面向数据报

    5、基于TCP的协议:HTTP、HTTPS、FTP、SMTP、TELNET

        基于UDP的协议:DNS、DHCP、TFTP、NFS

  • 相关阅读:
    C# 获取命名空间对应的程序集位置
    启用/禁用以太网的批处理,用于一个网卡切换本地网络和wifi使用(Win10)
    Gogs/Gitea 在 docker 中部署
    bash echo color
    python运行httpserver
    更改当前启动项,开关Hyper-V
    Win10更改CMD控制台的代码页和字体和字号
    ubuntu 编译 vim+lua
    CPU Usage (C#) 测试
    单击改变input的边框颜色
  • 原文地址:https://www.cnblogs.com/kingshine007/p/11343306.html
Copyright © 2011-2022 走看看