一、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