计算机网络面试(一)TCP

TCP报文格式

  • 16位源端口号,16位目的端口号
  • 32位序号:我们的每一个字节都被加上一个编号,而这里的序号指发送数据的位置,当SYN出现,序列码实际上是初始序列码(Initial Sequence Number,ISN),而第一个数据字节是ISN+1。
  • 32位确认序号:表示已经 接收到了这个序号之前的数据,还表示下一个准备接收的包的序列码。
  • 4位首部长度:4位包括TCP头大小,指示何处数据开始。每一位代表4个字节,4位最大15,首部最大为4*15=60个字节。
  • 保留(6位)
  • 标志:
  1. SYN(synchronous),建立联机。
  2. ACK(acknowledgement),确认。
  3. PSH(push),传输。
  4. FIN(finish),结束。
  5. RST(reset),重置。
  6. URG(urgent),紧急。 
  • 16位窗口大小:用来表示想收到的每个TCP数据段的大小。TCP的流量控制由连接的每一端通过声明的窗口大小来提供。窗口大小为字节数,起始于确认序号字段指明的值,这个值是接收端正期望接收的字节。窗口大小是一个16字节字段,因而窗口大小最大为65535字节。
  • 16位校验和:16位TCP头。源机器基于数据内容计算一个数值,收信息机要与源机器数值 结果完全一样,从而证明数据的有效性。检验和覆盖了整个的TCP报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的。CRC验证。
  • 16位紧急指针:指向后面是优先数据的字节,在URG标志设置了时才有效。如果URG标志没有被设置,紧急域作为填充。加快处理标示为紧急的数据段。
  • 选项:长度不定,但长度必须为1个字节。如果没有选项就表示这个1字节的域等于0。
  • 数据:该TCP协议包负载的数据。

TCP标志位:

TCP共有6个标志位,分别是:

  • SYN(synchronous),建立联机。
  • ACK(acknowledgement),确认。
  • PSH(push),传输。
  • FIN(finish),结束。
  • RST(reset),复位。在处理Telnet或rlogin等交互模式的连接时,该标志总是置位的。
  • URG(urgent),紧急。 

TCP的可靠性

  1. ***,确认应答,超时重传

    ***是TCP给发送的数据中每个字节都添加的一个编号,发送方和接收方在建立连接时都会随机生成一个初始***(不为0),确认应答用来表示对方已经接收到,并且确认序号用来表示xxx号之前的信息已经全部接收。

    超时重传是当发送数据后一段时间未接收到确认应答会在等待一定时间后进行重传。

    这个时间一般是2*RTT(往返时间)+一个偏差值。

  2. 滑动窗口机制
    定义一个窗口包括我们已经发但还没接收到应答和还没发但是可以发送的数据,这样我们就不用每次发送完一段数据都得等待应答才可以继续发送。窗口左边全部发送完了我们即可滑动窗口一直向右。发送方和接收方各拥有一个窗口。

  3. 慢开始,快重传,拥塞避免算法 (拥塞窗口和接收窗口是不同的)
    如果把窗口定的很大我们开始发送时网络中就会一次性出现大量的数据,可能会造成网络的拥塞,为了避免这种情况我们定义一个拥塞窗口,它一开始是1,每次收到确认应答后*2(慢开始),当它达到一个阈值后使用加数增长,
    每次超时重传后视为网络拥堵,将阈值减为当前窗口的一半,将当前拥塞窗口设为1,重新进入慢启动。(拥塞避免算法
    窗口的大小是由接收窗口和拥塞窗口的最小值决定。
    当我们接收到错误的***,例如当我们要接收的***1001-2000丢失了,我们后面会不停发送1001的确认应答,当发送端接收到第3个时,确认这段数据丢失,会开始重传。然后将慢启动阈值设置为当前窗口的一半,将拥塞窗口设置为阈值+3。注意,超时重传和快重传是不一样的。

TCP建立连接和断开连接的过程

计算机网络面试(一)TCP

发送方和接收方的状态

  1. 开始时CLOSED,服务器LISTIN,客户端发送之后进入SYN_SEND,服务器端收到后进入SYN_RECEIVE,连接建立后两边进入ESTABLISH。终止方发送第一个FIn 进去 FIn 1 _Wait ,收到Ack之后,还没收到另一端的FIN,进入FIN2_WAIT 被终止方接收到FIN,立即发送ACK,但还不能立即停的情况下,不会发送FIN,例如还有数据要发送,进入CLOSE_WAIT,等发送完FIN,进入LAST_ACK等待ACK,终止方接收到最后一个FIN,进入2MSL时间的TIME_WAIT。
  2. TIME_WAIT:客户端收到服务端的FIN包,并立即发出ACK包做最后的确认,在此之后的2MSL MAX segment lifetime时间称为TIME_WAIT状态。为了防止我的FIN发送出去没收到,需要重传。

三次握手:

  1. Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。
  2. Server收到数据包后由标志位SYN=1知道Client请求建立连接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认连接请求,Server进入SYN_RCVD状态。
  3. Client收到确认后,检查ack是否为J+1,ACK是否为1,如果正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,如果正确则连接建立成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间可以开始传输数据了。

为什么要三次握手

  • 三次握手的本质上是为了让发送方和接收方知道对方的***并且确认对方已经收到自己的***,如果只有两次而没有第三次,就没办法让接收方确认发送方已经知道了自己的***

SYN网络攻击:

  • 在三次握手过程中,Server发送SYN-ACK之后,收到Client的ACK之前的TCP连接称为半连接(half-open connect),此时Server处于SYN_RCVD状态,当收到ACK后,Server转入ESTABLISHED状态。SYN攻击就是Client在短时间内伪造大量不存在的IP地址,并向Server不断地发送SYN包,Server回复确认包,并等待Client的确认,由于源地址是不存在的,因此,Server需要不断重发直至超时,这些伪造的SYN包将产时间占用未连接队列,导致正常的SYN请求因为队列满而被丢弃,从而引起网络堵塞甚至系统瘫痪。SYN攻击时一种典型的DDOS攻击,检测SYN攻击的方式非常简单,即当Server上有大量半连接状态且源IP地址是随机的,则可以断定遭到SYN攻击了

TCP四次挥手

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭

(1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。(状态位FIN=1,发送seq=J)

(2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。(状态位ACK=1,发送ack=J+1)

(3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。(状态位FIN=1,发送seq=K)

(4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。(状态位ACK=1,ack=K+1)

注意此时客户端并未进入CLOSED状态,为了防止服务延迟,需要等待2MSL (Max Segment Lifetime)的时间,然后进入CLOSED状态。

为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?

 

一、保证TCP协议的全双工连接能够可靠关闭,如果Server没有收到Client最后回复的ACK时,它就会重发一个FIN,如果这时候Client已经CLOSED,Server就会收到RST而不是ACK。

二、保证这次连接的重复数据段从网络中消失,如果Client直接CLOSED,又发起一个新连接,由于新连接和老连接的端口是相同的,如果这时候Server还有信息延迟道法了,就会发送给新连接。所以我们要等待2MSL来保证本次连接所有数据都在网络中消失。