计网-TCP/IP

本文最后更新于:4 个月前

  • [x] TCP/IP 是网络层和传输层协议,是协议簇

  • [x] 如何理解 TCP (两点)

    TCP 是面向连接可靠传输,这里有两点,一是连接,二是可靠

    连接指的是两方要去通信肯定需要连接,连接可以是虚拟的,也可以是物理真实存在的

    TCP 的连接是一对 Socket 套接字

    可靠指的是两方是由 socket 中的一对 ip:prot 和 ip:port,当客户端发送数据时,由于 ip:port 和 ip:port 是网络上唯一的,保证了可靠性

  • [x] TCP连接三次握手的过程

    1. server 首先要处在 listen 状态监听端口

    2. client 发送 SYN ,client 进入同步已发送 syn-sent 状态

      SYN =1,seq = x,x 是自己初始化的序列号

    3. server 收到后(如果同意连接),会发出确认报文 SYN + ACK,server 进入同步收到 syn-revd 状态

      ACK = 1,SYN = 1,ack = x+1,seq = y

      确认号 ack 是 x+1

      y 是自己初始化的序列号

    4. client 收到 server 发送的 ACK 之后,还要再给服务端发送确认报文 ACK,此时,TCP建立, client 进入已建立链接 established 状态,开辟资源

    ack=1,ack=y+1,序列号 seq=x+1

    1. server 收到之后,进入 establish 状态,会开辟资源,此时双方可以开始通信了
  • [x] TCP 连接为什么需要发送最后第三次确认呢?

    如果使用的是两次握手建立连接,假设有这样一种场景:

    客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的 client 以为服务器没有收到,此时重新向服务器发送这条报文

    此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接

    此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个请求该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,但是再次建立连接之后没有传输任何数据,这会导致不必要的错误和资源的浪费

    同样的场景,如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认,由于服务器收不到确认,就不会开辟资源,避免了资源的浪费

  • [x] 四次挥手

    1. 首先,server 和 client 都是 established 状态

    2. client 发送连接释放报文 FIN,client 进入终止等待状态1 fin-wait-1

      fin =1,seq=u(前面已经传输的最后一个字节的序列号+1),

    3. server 收到连接释放 FIN 之后,发出确认报文 ACK,此时服务端进入关闭等待状态 close-wait

      ACK = 1,ack = u+1,seq = v

      此时 client 处于半关闭状态,即 client 不会发送数据了,但是 server 端还可以发送数据让 client 接收

    4. client 收到 server 发送的 ACK 之后,进入终止等待状态2 FIN-WAIT-2

    5. server 发送完数据后,再向 client 发送连接释放报文 FIN,此时 server 进入最后确认状态 LAST-ACK

      FIN = 1,ack = u+1,seq = w

    6. client 收到 FIN 之后,发送 ACK 确认,此时 client 进入时间等待状态 TIME-WAIT

      ACK =1,ack = w+1,seq = u+1

      此时 TCP 还没有释放,必须经过一个最长报文寿命 2*MSL 时间后,才进入 CLOSE 状态

    7. server 收到 ACK 之后,立即进入 CLOSE 关闭状态

      server 结束要比 client 早

  • [x] 为什么客户端最后还要等待2MSL? (两点)

    MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值

    第一,保证客户端发送的最后一个 ACK 报文能够到达 server

    因为这个 ACK 报文可能丢失

    站在服务器的角度来看,我已经发送了 FIN+ACK 报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次 FIN+ACK

    而客户端就能在这个 2MSL 时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器

    所以,TIME_WAIT 状态就是用来接收 server 重发可能丢失的 FIN+ACK 报文,并重新发送 ACK

    第二,防止类似与"三次握手"中提到了的"已经失效的连接请求报文段"出现在本连接中

    客户端发送完最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样新的连接中不会出现旧连接的请求报文

  • [x] 为什么建立连接是三次握手,关闭连接确是四次挥手呢?

    建立连接的时候,服务器在 LISTEN 状态下,收到建立连接请求的SYN报文后,把 ACK 和 SYN 放在一个报文里发送给客户端

    而关闭连接时,服务器收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意再关闭连接,因此,己方 ACK 和 FIN 一般都会分开发送,从而导致多了一次

  • [x] 如果已经建立了连接,但是客户端突然出现故障了怎么办?

    TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源

    服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔75秒发送一次

    若一连发送10个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接

参考博客

更深入