通信过程

![通信过程](/image/network/tcp 通信过程。png)

服务端:

  1. socket:建立 socket
  2. bind:绑定服务端 ip
  3. listen:开始监听
  4. accept:等待连接(阻塞)
  5. read/write:通信
  6. close:关闭连接

三次握手——建立通信过程

参考:TCP 的三次握手与四次挥手(详解+动图)

三次握手建立通信过程

涉及到状态:

  1. closed
  2. SYN_SENT
  3. SYN_RECV
  4. ESTABLISHED

四次挥手——断开连接

四次挥手释放过程

涉及到状态:

  1. ESTABLISHED
  2. FIN_WAIT1
  3. FIN_WAIT2

问题总结

  1. tcp 的 2MSL 问题

    MSL:Maximum Segment Lifetime,最长报文时间

    2MSL 即两倍的 MSL ,TCP 的 TIME_WAIT 状态也称为 2MSL 等待状态,

    当 TCP 的一端发起主动关闭,在发出最后一个 ACK 包后,

    即第 3 次握手完成后发送了第四次握手的 ACK 包后就进入了 TIME_WAIT 状态,

    必须在此状态上停留两倍的 MSL 时间,

    等待 2MSL 时间主要目的是怕最后一个 ACK 包对方(server)没收到,

    那么对方在超时后将重发第三次挥手的 FIN 包,

    主动关闭端接到重发的 FIN 包后可以再发一个 ACK 应答包。

    在 TIME_WAIT 状态时两端的端口不能使用,要等到 2MSL 时间结束才可继续使用。

    当连接处于 2MSL 等待阶段时任何迟到的报文段都将被丢弃。

    不过在实际应用中可以通过设置 SO_REUSEADDR 选项达到不必等待 2MSL 时间结束再使用此端口。

    其他总结:

    第一,保证客户端发送的最后一个 ACK 报文能够到达服务器,因为这个 ACK 报文可能丢失,站在服务器的角度看来,我已经发送了 FIN+ACK 报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个 2MSL 时间段内收到这个重传的报文,接着给出回应报文,并且会重启 2MSL 计时器。

    第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个 2MSL 时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

  2. 为什么建立连接是三次握手,关闭连接确是四次挥手呢?

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

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

  3. 为什么不能用两次握手进行连接?

    3 次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

    现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机 S 和 C 之间的通信,假定 C 给 S 发送一个连接请求分组,S 收到了这个分组,并发 送了确认应答分组。按照两次握手的协定,S 认为连接已经成功地建立了,可以开始发送数据分组。可是,C 在 S 的应答分组在传输中被丢失的情况下,将不知道 S 是否已准备好,不知道 S 建立什么样的序列号,C 甚至怀疑 S 是否收到自己的连接请求分组。在这种情况下,C 认为连接还未建立成功,将忽略 S 发来的任何数据分 组,只等待连接确认应答分组。而 S 在发出的分组超时后,重复发送同样的分组。这样就形成了死锁

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

    TCP 还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。服务器每收到一次客户端的请求后都会重新复位这个计时器,时间通常是设置为 2 小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔 75 秒钟发送一次。若一连发送 10 个探测报文仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。

  5. 一个 TCP 可以建立多少 http 连接? 多个,established 期间随意

  6. 浏览器向服务器发出请求,但中间发生丢包,最后服务器返回了 200OK,分析一下

    1. 请求和响应属于 http 服务
    2. 丢包和重传属于 TCP
    3. Http 不关心这个事儿——丢包,即使丢包,也可正常返回 200