TCP/UDP

TCP/UDP协议是TCP/IP协议的核心,位于TCP/IP协议的传输层,用于提可靠传输。

TCP

传输控制协议。位于传输层,提供面向连接,可靠的字节流服务并且提供超时重发,丢弃重复数据,检验数据,流量控制等功能保证数据能从一端传到另一端;字节流是指为方便传输将大块数据分割成以报文为单位的数据包进行管理;可靠的传输服务是指能将数据准确可靠的传送给对方(能够确认数据最终是否到达对方)。

UDP

用户数据报协议。面向数据报的传输层协议,提供面向无连接,不可靠的数据流传输服务,传输速度快。只负责传输用户发给IP层的数据报,不提供报文到达确认,排序以及流量控制。

TCP保证可靠传输的方式
  • 校验和:
    目的:检测数据在传输过程中的变化,如果接收端计算出的校验和跟发送方的校验和比较有差错,TCP将丢弃这个报文段并不确认收到此报文段;

    校验和的计算方式:
    实现过程:把发送的进行检验的数据和运算的数据分成若干个16位的位串,每个位串看成一个二进制数,对这些16位的二进制数进行1的补码和运算(带循环进位(end round carry)的加法,最高位有进位应循环进到最低位),累加的结果再取反码即生成了检验码,将检验码放入检验和字段中。
    注意: 如果接收方比对校验和与发送方不一致,那么数据一定传输有误。但是如果接收方比对校验和与发送方一致,数据不一定传输成功。

  • 确认应答与***:
    ***:TCP传输时将每个字节的数据都进行了编号,这就是***。***能将接收到的数据根据***排序,并且去掉重复***的数据。
    确认应答:TCP传输过程中每次接收方收到数据后,都会发送ACK报文对传输方进行确认应答。ACK报文中带有对应的***,告诉发送方,接收到了哪些数据,下一次的数据从哪里发。

  • 超时重传:
    在进行TCP传输时,由于确认应答和***机制,发送端在发送一部分数据后,会等待接收端发送的ACK报文。但由于网络原因可能会出现:

  1. 数据在发送过程中发生了丢包,接收端没有接收到;
  2. 接收端接收到数据后,发送了ACK报文,但ACK报文发生了丢包,发送端没有接收到。

TCP使用超时重传机制来解决问题,发送端在发送数据之后,会等待一段时间,如果时间到达后,还没收到ACK报文,则重新发送刚才的数据。接收端在接收到重发的数据,会从***中确认数据是否已经接收过,如果没有接收过,则接收数据,并返回ACK报文;如果已经接收过,则直接抛弃,返回ACK报文。

  • 连接管理:
    三次握手,四次挥手(见下文)

    滑动窗口(连续ARQ协议,可以连续发出若干个分组等待确认):流量控制和拥塞控制都是使用滑动窗口来实现的;滑动窗口是指发送缓存中可以发送的数据***范围。只有在滑动窗口之内的数据才能被发送,并且在发送数据,接收到ACK报文之后,该窗口会向前滑动。
    滑动窗口的大小由流量窗口和拥塞窗口决定。

  • 流量控制:
    为什么需要流量控制: 接收端在接收到数据后,需要对其进行处理。如果发送端的发送速度太快,导致接收端的结束缓冲区很快的填充满了,而发送端继续发送数据就会造成数据包丢失,导致重传等一系列反应。
    而流量控制就是TCP根据接收端对数据的处理能力,决定发送端的发送速度。
    主要方式是 在返回的ACK中包含自己接收窗口的大小,滑动窗口会根据这个数据来控制发送方的数据发送。窗口的大小实际上是接收端接收数据缓冲区的剩余大小
    注意: 如果发送端接收到的窗口大小为0时,发送端会停止发送数据,并定期地向接收端发送一个1字节的探测报文,对方会在此时回应自身的接收窗口大小,如果结果仍未0,则重设持续计时器,继续等待。

  • 拥塞控制:
    常用方法:
    1. 慢开始、拥塞控制: 慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,由小到大逐渐增加拥塞窗口的大小。
    2. 快重传、快恢复: 快重传要求接收方在收到一个失序的报文段后就立即发出重复确认,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期。

流量控制和拥塞控制的区别:
  • 流量控制作用于接收端,用来控制发送端的发送速度,防止分组丢失。
  • 拥塞控制作用于网络,防止过多的数据注入到网络中。这样可以使网络中的路由器或链路不致过载。
TCP三次握手过程
  • seq:***,4字节,32位,用来标志数据包的顺序。TCP是面向字节流的,通过 TCP 传送的字节流中的每个字节都按顺序编号,***就是发送的报文段第一个字节的编号。
  • ack:确认号,是指期望对方发送的下一个数据包的第一个字节的序号(***)。
  • TCP常用标志位
字段 含义
URG 紧急指针是否有效。为1,表示某一位需要被优先处理
ACK 确认好是否有效,一般置为1
PSH 提示接收端应用程序立即从TCP缓冲区把数据读走
RST 对方要求重新简历链接,复位
SYN 请求简历链接,并在其***的字段进行***的初始值设置,建立连接,设置为1;消耗一个字节
TIN 希望断开连接,消耗一个字节

过程图解(盗的图)
TCP/UDP
过程描述:
1. 客户端发送***为x的数据包给服务端,标志位SYN=1,表示请求建立TCP连接;客户端进入SYN-SENT等待状态;
2. 服务端收到数据包,确认数据包设置确认号ack=x+1,表示收到***为x的数据包,希望发送方发送***为x+1的数据包;向客户端发送一个SYN/ACK数据包,SYN=1,ACK=1,数据包的***为seq = y。
服务端从LISTEN进入SYN-RECVD;
3. 客户端接收到数据包,向服务端发送ACK=1的数据包,ack=y+1,双方建立TCP连接ESTAB-LISHED,开始传输数据。

Q: 确认ack为什么是ack = seq+1?

seq是报文第一个字节的编号,ack表示期望收到的下一个数据包第一个字节的编号,在握手过程种还没有数据传输,仅仅是SYN消耗了一个字节,所以服务端期望接收到的下一个报文的seq=上一个seq+1;如果有数据传输,那么下一个报文段的seq应该是上一个seq+上一个报文的字节数;

Q:为什么是三次握手?不能是两次?四次?

明确点:

  1. TCP是可靠传输,对数据的传送有确认机制,SYN/FIN被设计成一个字节的数据。
  2. 双方握手是为了让通信双方做好接收数据的准备,就是协商,交换数据包***的过程,来保证可靠,高效传输。
四次握手过程:
  1. A发送自己的***和SYN标志位给B,让B知道什么样的数据编号是合法的;同时对每个编号的字节数据进行确认。
  2. B收到***和SYN标志位必须要给A发送一个ACK确认已经收到A发送的数据;
  3. 同时B又要向A发送自己的数据包***和同步信号,让A做好准备接收数据;
  4. A收到B的同步信号,又给B发送一个ACK确认收到。

到此才算A和B协商完了彼此的***范围,建立了TCP连接,可以传输数据。在四次握手过程中,2,3两步可以合并以提高连接的效率,因此只需要三次。

二次握手过程:
  1. A发送同步信号和***给B;
  2. B发送ACK/SYN信号和***给A;

那么问题来了,在两次握手的过程中, A接收到B的同步信号后并没有确认自己是否收到B的***,就是B无法确认A是否收到了自己的同步信号 ,如果这个同步信号丢失了,A和B就B的初始***将无法达成一致。因此不能两次握手。

Q:A发给B的ACK丢了怎么办?

B没有收到A的ACK:

  1. 如果双方都没有数据传输那么B会超时重传自己的SYN同步信号,一直到收到A的ACK为止。
  2. 如果A有数据发送,B收到A的 Data + ACK,自然会切换为established 状态,并接受A的 Data。
  3. 此种情况B不能发送数据,会一直超时重传SYN/ACK信号,直到收到A的ACK确认。

A不会超时重传ACK,因为ACK没有数据,TCP不会为没有数据的ACK超时重传。

Q:第一个包,即A发给B的SYN 中途被丢,没有到达B,怎么办?

A会周期性超时重传SYN,直到收到B的确认;

Q: 第二个包,即B发给A的SYN +ACK 中途被丢,没有到达A,怎么办?

B会周期性超时重传,直到收到A的确认

TCP四次挥手过程:

过程图解:
TCP/UDP
挥手过程:

  1. 客户端向服务端发送释放连接的请求FIN=1,seq = u,***;客户端进入FIN-WAIT-1状态;不能发送数据(这里的数据不包括确认报文),能接收服务端发送的数据以及发送确认报文。
  2. 服务端接收到客户端发送的请求,确认客户端想释放连接的请求,服务端进入CLOSED-WAIT状态,同时给客户端发送确认报文ACK=1,seq=v,ack=u+1,同时通知应用进程;客户端接收到服务端的确认报文后进入FIN-WAIT-2状态。
  3. 确认报文后,服务端可以继续向服务端发送没有发送完的数据,当数据发送完后服务端向客户端发送释放连接的请求。FIN=1,传输了数据后,seq = w,ack = u+1。服务端进入LAST-ACK阶段,并且停止在服务器端到客户端的方向上发送数据,但是服务器端仍然能够接收从客户端传输过来的数据。
  4. 客户端接收到服务端释放连接的请求后,进入TIME-WAIT阶段,并向服务器端发送一段确认报文,ACK=1,seq=u+1,ack=w+1;服务器端收到从客户端发出的TCP报文之后结束LAST-ACK阶段,进入CLOSED阶段。由此正式确认关闭服务器端到客户端方向上的连接。
  5. 客户端等待完2MSL之后,结束TIME-WAIT阶段,进入CLOSED阶段,由此完成“四次挥手”。
Q:客户端为什么要等待2MS?

确认服务器端是否收到客户端发出的ACK确认报文**。MSL指的是Maximum Segment Lifetime:一段TCP报文在传输过程中的最大生命周期。**
客户端发送ACK到服务端最大时长为1MS,服务端发送FIN到客户端最大时长为1MSL。服务器端在1MSL内没有收到客户端发出的ACK确认报文,就会再次向客户端发出FIN。

如果客户在向服务端发送了ACK之后,在2MSL内再次收到服务端发来的FIN说明服务器端由于各种原因没有接收到客户端发出的ACK确认报文。客户端再次向服务器端发出ACK确认报文,计时器重置,重新开始2MSL的计时;

如果客户端在2MSL内没有接收到服务端发送的FIN则说明服务器端正常接收了ACK确认报文,客户端可以进入CLOSED阶段,完成“四次挥手”。

Q:为什么是四次挥手?不是三次?

前两次挥手是为了让服务器知道客户端要释放连接,也让客户端知道服务端已经明白了自己要释放连接;(客户端-服务端释放);
后两次挥手是为了让客户端知道服务端要释放连接,也让服务端知道客户端已经明白了自己要释放连接;(服务端-客户端)

Q:为什么服务端的确认报文和释放连接请求不能同时发送,像三次握手一样?

至于为什么不是三次而是四次?为什么不能把2,3确认报文和释放连接请求合成一步,是因为:
客户端请求释放连接的时候,服务端可能还在向客户端发送数据不能立即释放连接,只能先发送确认报文(经过CLOSE-WAIT阶段准备好释放连接之后,才能返回FIN释放连接报文。);当数据传输结束之后在发送服务端释放连接报文。

而建立连接时,被动方服务器端结束CLOSED阶段进入“握手”阶段并不需要任何准备,可以直接返回SYN和ACK报文,开始建立连接。