图文详解三次握手和四次挥手以及常见问题

三次握手发生在TCP客户端想要与TCP服务端建立连接时

四次挥手发生在TCP客户端想要与TCP服务端释放连接时

起初 , 两个TCP进程都处于关闭状态

一开始TCP服务进程首先创建传输控制块 , 里面存储传输需要的一些重要信息

    • TCP连接表
    • 指向发送和接收缓存的指针
    • 指向重传队列的指针
    • 当前的发送和接收序号
  • 然后TCP服务进程就进入监听状态 , 等待TCP客户端的连接请求
    • 这里要注意 , TCP服务进程是被动等待TCP客户进程的连接请求的
  • TCP客户进程也会创建传输控制块

三次握手

  • (一握:客户端--->服务端)首先客户端向服务端发送TCP请求报文段 , 客户端进入同步已发送状态
    • 请求报文段首部的同部位SYN设置为1 , 以此来表明这是一个TCP连接请求报文段
    • 序号字段seq设置为x , 作为TCP客户端所选择的初始序号
    • 这里要注意 , TCP规定SYN设置为1的报文段不可以携带数据 ,但是会消耗一个序号
  • (二握:服务端--->客户端)TCP服务端同意连接请求 , 并向TCP客户端发送TCP连接请求确认报文段 , 服务端进入同步已接收状态
    • 该确认报文段中首部的同部位SYN设置为1 , 确认位ACK也设置为1 , 以此来表明这是一个TCP连接请求确认报文段
    • 序号字段seq设置为y , 作为TCP服务端所选择的初始序号
    • 确认号字段ack的值设置为x+1 , 这是对TCP客户进程所选择的初始序号的确认
    • 该报文段依然不可以携带数据 , 但是会消耗一个序号
  • (三握:客户端--->服务端)然后TCP客户端向服务端发送一个普通的TCP确认报文段 , 客户端进入连接已建立状态
    • 该报文段首部中的确认位ACK被设置为1 , 表明这是一个普通的TCP确认报文段
    • 序号字段seq设置为x+1 , 这是因为客户进程发送的第一个TCP报文段的序号为x , 所以这第二个序号就要设置为x+1
    • 确认号字段ack的值设置为y+1 , 这是对服务器进程所选择的初始序号的确认。
    • 这里要注意 TCP规定普通的TCP确认报文段可以携带数据。如果不携带数据, 就不消耗序号
    • 当服务端接收到这个报文段之后, 服务端进入连接已建立状态

 为何需要发送第三次普通的确认报文(是否可以使用两报文握手)

  • 防止已失效的连接请求报文突然又传输到了服务端
    • 这里我们来举一个例子 , 假设客户端先发送了连接请求报文 , 然后这个报文丢失了
    • 然后客户端再次发送了一个连接请求报文 , 这一次服务器接收到了 ,然后给客户端发送请求确认报文 , 并且服务端进入连接已建立状态
    • 客户端收到此连接确认报文后 , 进入连接已建立状态 , 然后开始传输数据
    • 一段时间后正常结束了
    • 这个时候 , 客户端第一次发送的那个丢失了连接请求报文段到达了服务端 , 服务端就认为这是一个新的连接请求 , 然后服务端给客户端发送了连接请求确认报文, 并且将服务端的状态改为连接已建立
    • 而客户端因为没有发送过请求报文, 所以就不会理会这个请求确认报文, 这样就会造成很严重的资源浪费

四次挥手

  • (一挥:客户端--->服务端)首先由客户端发送终止请求报文段 , 客户端进入终止等待1状态
    • 该报文首部的终止位FIN设为1 , 确认位ACK设为1 , 以此来表明这是一个TCP连接释放报文段 , 确认位是对数据传输阶段发送报文段的确认 , 可以没有
    • 序号seq设置为u(TCP客户进程之前以传送过的数据的最后一个字节序号加1) ,
    • 确认号ack设置为v(这个是TCP客户端进程之前已经收到数据的最后一个字节的序号加1)
  • (二挥:服务端--->客户端)服务端收到客户端发送的释放请求报文段后 , 会发送一个普通的TCP确认报文段 , 服务端进入关闭等待状态
    • 该报文段确认位ACK的的值设为1
    • 序号seq设置为v , 它等于TCP服务器进程之前已传送过的数据的最后—个字节的序号加1 , 与之前收到的TCP连接释放报文段中的确认号匹配。
    • 确认号ack设置为u+1 , 这是对TCP连接释放报文段的确认
    • 此时TCP服务进程要提醒上层应用进程 , 客户端要断开与服务端的TCP连接
    • 这个时候 , 从TCP客户进程到TCP服务器进程这个方向的连接就释放了。TCP连接属于半关闭状态 , 客户端已经没有数据要发送了
    • 但是如果服务端还有数据要发送的话, 客户端仍然需要接收
    • TCP客户端收到这个确认报文段后, 客户端进入终止等待2状态 , (等待TCP服务器进程发出的TCP连接释放报文段)
  • (三挥:服务端--->客户端)服务端没有数据要发送了 , TCP服务器进程发送TCP连接释放报文段 服务端进入最后确认状态
    • 该报文段首部中的终止位FIN设为1 , 表明这是一个连接释放报文段
    • 确认位ACK的值也设置为1, 对之前收到的报文段进行确认
    • 我们可以假定序号seq的值为w , 因为在半关闭状态下, tcp服务进程可能有发送了一些数据
    • 确认号ack的值为u+1 , 这是对第一次收到的TCP连接释放报文段的重复确认。
  • (四挥:客户端--->服务端)TCP客户进程收到TCP连接释放报文段后 , 必须针对该报文段发送普通的TCP确认报文段 , 此时客户端进入时间等待状态
    • 该报文段首部中的确认位ACK的值被设置为1 , 表明这是一个普通的TCP确认报文段
    • 序号seg字段的值设置为u+1 , 因为第一次客户端发送给服务端的释放请求报文段会消耗一个序号
    • 确认号ack字段的值设置为w+1 , 这是对所收到的TCP连接释放报文段的确认。
    • TCP服务器进程收到该报文段后 服务端就进入关闭状态。
    • 但是 , TCP客户进程还要经过2MSL后才能进入关闭状态。
    • MSL : 最长报文段寿命 , 根据不同的使用情况来决定

 

为什么TCP发送完确认报文段后要等待2MSL时间

    • 假如第四次客户端向服务端发送确认报文段之后就直接进入关闭状态 , 而该确认报文段丢失了
    • 这样就会造成服务端对第三次发送的连接释放报文段的超时重传
    • 而客户端已经处于关闭状态了 , 就不会理睬这个报文段
    • 这就会造成TCP服务器进程反复重传TCP连接释放报文段 , 并且服务端会一直处于最后确认状态, 无法进入关闭状态
    • 所以客户端等待着2MSL , 可以确认服务端收到了最后一个确认报文, 并且服务端进入了关闭状态
    • 还有一点就是 , 在客户端等待的这2MSL时间内 , 可以确保此次连接时间内所产生的所有报文段都从网络上消失 , 避免下一次新连接时, 出现旧的报文段

服务端的保活计时器 , 防止客户端出现故障

    • TCP服务器进程每收到一次TCP客户进程的数据,就重新设置并启动保活计时器(2小时定时),
    • 若保活计时器定时周期内未收到TCP客户进程发来的数据,则当保活计时器到时后,TCP服务器进程就向TCP客户进程发送一个探测报文段,以后则每隔75秒钟发送一次。若一连发送10个探测报文段后仍无TCP客户进程的响应,TCP服务器进程就认为TCP客户进程所在主机出了故障,接着就关闭这个连接。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值