TCPIP三次握手四次挥手及所有相关问题解释


纠错注释: 今天十分有幸遇到字节的技术面试官, 小姐姐给提出了很多细节和中肯的建议, 首先在本文中提到的tcp/IP是否是安全的问题, 并没有任何案例能证明tcp/IP连接是安全的, 因为安全这个性能是在应用层的数据上才能展示出来, 比如账户的密码, 在tcp传输过程中只是报文形式, 并没有跟安全相关; 最后还是要感谢字节小姐姐的提醒, 受益匪浅.
总之: tcp链接是可靠的, 保证报文的传输

1. TCP报文格式

  • 32位序号: 当前报文的标识序列, 由计算机随机生成, 下文的seq
  • 32位确认序号: 一般是上一个收到的报文的seq+1, 表明上一个报文已收到, 下文的ack
  • SYN: 发起新连接
  • ACK: 响应标识符
  • FIN: 中断一个连接
  • RES: 对方请求重新建立连接, 复位标识符, 比如server没有收到第三次挥手, 会在client发送数据后回应一个RES让client重新建立连接
  • URG: 紧急指针是否有效, 1标识某一位需要优先处理
  • PSH: 提示接收端应用程序应该立即从TCP缓冲区把数据读走

2. TCP三次握手

在这里插入图片描述

  1. client发送请求连接报文, SYN=1, 生成随机的32位初始化序列号seq=x, 此时如果server收到后, 就知道在请求建立连接了

  2. server发送同意请求连接, SYN=1, 也随机生成一个32位初始化系列号seq=y, ACK=1表示确认消息有效, 同时带一个消息确认序号ack=seq+1 = x+1

  3. 此时client收到了来自server的确认信息, 它笑了, 因为此时它既可以向server发送信息了, 也可以接收server的信息了, 但是server还不能确定client到底收没收到信息, 所以为了让server知道他既能收到client信息, 也能成功向client发送信息, 所以此时需要client在给server回应一个确认包, 证明了server能给client发送小心了; ACK=1, ack=y+1; 这里同时解释了为何需要三次而不是两次握手

    以上就保证了client能收发server信息, server也能收发client信息, 也就是全双工的通信, 同时, 上述也说明了, 两次握手不能实现全双工的通信机制, 所以最少需要三次握手

2.1. 三次握手过程中对方未接收到信息的情况分析

  1. 如果server没有收到SYN请求, 或者client没有收到server回应: client间隔一段时间重新发送SYN同步报文, 若还没回应, 重复上述过程到发送上限tcp_syn_retries, 这时候建立连接的connect系统调用返回-1, 这是errno为etimeout
  2. 如果供给client的server地址错误或者按照client路由无法到达server, 某个路由器会回应一个目的不可达的ICMP错误信息, 同样connect系统调用返回-1, 这是errno为e_addr_no_tavail
  3. server未收到第三次握手: server未收到client发送过来的ACK报文, 同样采取上述重传机制, 如果重传次数超过tcp_syn_retries, accept系统调用返回-1, server端连接建立失败. 注意: client端单方面建立成功, 即client向server发送数据, 但是server端的accept系统调用已经返回, server没有监听, 而 tcp协议是一个可靠安全的全双工协议, 因此server接收来自client发送的数据时, 会发送RST报文给client(复位client, 消除client单方面连接状态)

3. 四次挥手

  1. 客户端想要断开链接, 报文里面需要将标致位FIN=1, seq=m(这就不是随机生成的, 而是通过收发报文增长上来的),
  2. 服务端应答:ACK=1, ack=m+1, 于是客户端就确定了服务端收到了自己的消息
  3. 紧接着服务端又发送一个断开连接请求, FIN=1, seq=n,
  4. 客户端发送一个消息确认包回去 ,ACK=1, ack=n+1

3.1. 为何第二三次挥手不合并?

首先tcp/IP是安全的, 首先client申请断开连接 服务端回应client后, client已经准备好了断开, 并且不会再发送数据了, 但是此时客户端无法确定服务端有没有消息会发送, 所以必须拆开进行 ,先服务端发送给client端告诉他我收到了你的请求, 你可以不给我发送数据了, 但是我需要等等确定好没有数据需要发送了再说, 客户端就开始等, 如果服务端确定没有数据需要发送了, 这个时候才会向客户端发送断开连接的请求报文, 这时候客户端收到服务端的断开请求后, 回应服务端, 然后双方结束, 断开双方;

4. 相关问题

4.1. TCP/IP的三次握手四次挥手的机制么?

答: 面试官您好, 这个问题我是知道的, TCP/IP这是一个传输层的一个面向连接的可靠安全的一个传输协 议, 三次握手的机制, 是为了保证能建立一个安全可靠的连接, 第一次握手是由客户端发起, 客户端会向服务端发送一个报文, 报文里面SYN位是1, 当服务端看到这个标志位 置1, 那么服务端就知道这是客户端要建立连接, 确认消息包, ack置一, 当前两次握手之后, 客户端就能够确定客户端既能给server发送, 也能收到server的数据, 但是两次握手是不够的, 因为到目前为止, 服务端只知道自己能够收到client的消息, 还无法确定client能不能收到自己的消息, 所以还要进行第三次握手, 也就是client给server回应一个确定收到的报文, 即ACK=1, 当server收到客户端的确认报文后, 此时双方才能确定既可以接收也可以发送数据给对方, 成功建立了一个全双工通信的连接

4.2. 为什么TCP连接的时候是三次, 关闭的时候是四次

因为只有在客户端和服务端都没有数据要发送的时候才能断开tcp连接, 而客户端发出的FIN报文只能保证客户端没有数据需要发送了, 但是服务端还没有数据需要发送给客户端此时还不确定 , 所以服务端收到客户端FIN报文后只能先回应一个确认报文告诉客户端我收到了你的断开请求, 我不在接收你的消息了, 但我可能还有一些数据没有发完给你, 你等我一会, 当服务端数据发送完毕后, 服务端才会给客户端发送一个FIN报文, 因此不能一次性将确认报文和FIN报文同时发送给客户端, 因此需要多出来一次

4.3. 为什么客户端发出第四次挥手的确认报文后要等2MSL时间才释放TCP链接?

2MSL(2 * Maximum Segment Lifetime,两倍的报文段最大存活时间)

这里需要考虑丢包的问题, 如果第四次挥手的报文丢失, 服务端没有收到确认ack报文, 就会重新发第三次挥手的报文, 这样报文一去一回最长时间是2ms, 所以需要等待这么长时间来确认服务端确实已经收到了

4.4. 如果已经建立了链接, 但是客户端突然故障怎么办?

TCP设有保活计时器, 客户端出现故障, 服务器不能一直等待, 会浪费资源; 服务器每收到一次客户端请求, 都会重新复位计时器, 时间通常设置为2h, 如果2h没有收到客户端任何数据, 服务器就会发送一个探测报文段(75s一次), 若一连10个探测报文没有反应, 服务器认为客户端出现故障,关闭连接;

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

落子无悔!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值