一、TCP的报文结构

红色圈标出的是在讨论三次握手和四次挥手时会用到的首部字段:

  • 顺序号(seq):TCP对从网络层传下来的数据报文进行分组,分成一段一段的TCP报文段,并对这些报文段进行编号。seq为该TCP报文段的序号。
  • 应答号(ack):期望收到的对方的报文段的序号,用来对已经收到的报文进行确认,如果ack=a+1,那么表示seq<=a的报文都已经收到了。
  • ACK:应答号有效性标志(只有当ACK=1时,ack字段才有效)。一旦一个连接建立起来,该标志总被置为1。
  • SYN:同步序号标志(建立连接时候使用)。
  • FIN:传输数据结束标志(断开连接时使用)。

二、建立TCP连接——三次握手

2.1 三次握手的过程

通信双方都可以发起连接。但是在Client-Server模型中,一般都是客户端主动向服务器发起连接,所以这里以这样的例子做演示。

0. 最初服务器处于LISTEN状态。

1.(第1次握手) 客户端向服务器发送连接请求报文(SYN=1, ACK=0, seq=0),之后客户端进入SYN-SENT状态。

  • ACK=0表示该报文中的ack字段是无效的,因为这个报文是用来请求建立一个新的连接的,并不是对ack所指报文段的应答。
  • seq=0表示这是新会话中客户端发出的的第一个报文段。

2. (第2次握手)服务器收到连接请求报文后,如果同意建立连接,则发出确认连接报文(SYN=1, ACK=1, seq=0, ack=1),之后服务器进入SYN-RECEIVED状态。

  • seq=0表示这是新会话中服务器发出的第一个报文段。
  • ack=1表示服务器已经收到客户端发出的序号为0的报文了。(ACK=1表示这个ack是有效的)

3. (第3次握手)客户端收到服务器的确认连接报文之后,还要再发出一个确认 收到服务器的确认连接报文的 确认报文(ACK=1, seq=1, ack=1),之后客户端进入ESTABLISHED状态,即客户端认为连接已经建立了。

4. 服务器收到来自客户端的确认报文之后进入ESTABLISHED状态,表示服务器认为连接已经建立了。

2.2 为什么要进行3次握手?

理解角度一

三次握手的目的是建立可靠的通信信道,所谓可靠的通信信道最基本的要求就是通信双方的数据发送和接收都是正常的。

因此,三次握手的主要目的是双方确认自己与对方的发送和接收都是正常的

  客户端 服务器
第1次握手 —— 客户端发送了一个报文并且我收到了-->客户端发送正常;服务器接受正常(从客户端到服务器的单向连接正常)
第2次握手

服务器发送了一条确认报文说明我刚才发的服务器收到了-->客户端发送正常;服务器接受正常(从客户端到服务器的单向连接正常)

服务器发的这条报文我收到了-->客户端接收正常;服务器发送正常(从服务器到客户端的单向连接正常)

——
第3次握手 —— 客户端发送了一条确认报文说明我刚才发的客户端收到了-->客户端接收正常;服务器发送正常(从服务器到客户端的单向连接正常)

从这个角度理解“为什么一定要3次握手,如果是2次握手会怎样?”,答案是:如果只有两次握手,对服务器来说,只验证了从客户端到服务器的单向连接正常,而从服务器到客户端的单向连接是否正常还不知道,需要通过第3次握手来获知。

理解角度二

通信的某一方进入ESTABLISHED状态的条件该方已经获知以下信息:①双方都确认要建立连接(双方都有建立连接的意向),②对方知道 我已经确认建立连接(对方确实会建立连接)。

注意:只知道对方有建立连接的意向是不够的,一定要确实知道他真的会建立连接才可以。而如果对方知道我已经确认连接就可以认为对方确实会建立连接。

  客户端 服务器
第1次握手 客户端有建立连接的意向

客户端发来了请求连接报文 --> 客户端有建立连接的意向;

第2次握手

服务器发回了确认连接报文-->服务器有建立连接的意向;

服务器能发回报文说明服务器已经收到我的请求连接报文了,即服务器已经知道我有建立连接的意向了 --> 服务器确实会建立连接

我返回给客户端确认连接报文 --> 服务器有建立连接的意向
第3次握手   客户端发出了确认 收到服务器的确认连接报文的 确认报文,说明客户端收到了我发出的确认连接报文,即客户端已经知道我确认建立连接了 --> 客户端确实会建立连接

从这个角度理解“为什么一定要3次握手,如果是2次握手会怎样?”,答案是:如果只有两次握手,对服务器来说,并不能确定客户端确实会建立连接,所以服务器是不会贸然进入ESTABLISHED状态的。

2.3 实例

三、释放TCP连接——四次挥手

3.1 四次挥手的过程

通信双方都可以释放连接,这里以客户端先发起释放连接的申请为例。

1. (第1次挥手)客户端发出释放连接报文(FIN=1, seq=u),声明自己已经没有数据要发送了,之后进入FIN-WAIT-1状态(等待对方对FIN的回复的状态)。

2. (第2次挥手)服务器收到释放连接报文,发出确认报文(ACK=1, seq=v, ack=u+1),之后服务器进入CLOSE-WAIT状态。在这一状态下,服务器如果还有数据要发,就继续发送数据给客户端。因为这时客户端已经不会再发数据了,所以这些从服务器发出去的数据的ack字段都是u+1。

3. (第3次挥手)服务器也没有要发的数据了,就发出释放连接报文(FIN=1, ACK=1, seq=w, ack=u+1)对此进行声明,之后服务器进入LASK-ACK状态(等待对方对FIN的回复的状态)。

4. (第4次挥手)客户端收到服务器发来的释放连接报文后,发出确认报文(ACK=1, seq=u+1, ack=w+1),之后进入TIME-WAIT状态等待2MSL(Maximum Segment Lifetime)后进入CLOSED状态。

5. 服务器收到客户端发来的确认报文后进入CLOSED状态。

3.2 为什么要4次挥手?

四次挥手的目的是断开连接,那么什么时候就可以断开连接了呢?当这条通信线路已经没有用了,即这条通信线路上不会再有数据的时候就可以断开连接了。

可以认为FIN报文是用来告诉对方我已经没有数据要发了,收到FIN报文的确认报文意味着对方也知道我不会再发数据了。一次FIN报文的交互意味着“一方将不再发数据”这一信息传播到了通信线路两端。之前有一个错误的理解,认为一次FIN报文的交互意味着单向连接的断开,这是不对的。因为这是一个全双工的连接,而不是两个单工连接。所以认为第1、2次挥手之后就断开了从客户端到服务器的连接就关闭了是不正确的,这只是说客户端告诉服务器:“我已经没有数据要发了,看你还有没有数据要发,要是没了我们就断开连接吧。”纠结这一个细节的原因在于:如果认为此时单向连接断开了,那就无法合理解释第4次挥手了,因为这样的话第4次挥手的确认报文服务器是不可能收到的。

因此需要进行2次FIN报文的交互,也就是4次挥手,来保证“双方都不会再发数据”这一消息传播到了通信线路两端。

3.3 为什么第4次挥手之后还要等2MSL?

第4次挥手之后,客户端已经知道“双方都不会再发数据”,那为什么还要再等2MSL呢?这个2MSL是在等什么?

设想这样一种情形:如果第4次挥手的报文丢失了会怎么样?

如果第4次挥手的报文丢失了,第3次挥手发出的释放连接报文在一段时间内没有得到回复,服务器必然会再发一次释放连接报文。如果是这样的话,客户端就得要保证能收到重传的报文并对其做出回复(并重置2MSL计时器)。

要保证能收到重传报文,客户端需要再等多长时间?

客户端发出第4次挥手的确认报文后,如果能到在MSL时间内肯定就到了;如果到不了,MSL时间内服务器也会发出重传的报文,这个重传的报文最多需要MSL时间就能收到。所以客户端需要再等2MSL时间。这个2MSL时间是在等如果可能有的重传报文。

3.4 实例

面试准备——计算机网络(TCP的三次握手和四次挥手)的更多相关文章

  1. 【图解】给面试官解释TCP的三次握手与四次挥手-Web运用原理及网络基础

    作者 | Jeskson 来源 | 达达前端小酒馆 轻松了解HTTP协议 为什么要学习网络协议呢?为什么要学习计算机完了呢?显然这很重要,至少能够帮助你找到工作的原因之一,学习网络知识点太多太多,没有 ...

  2. 【计算机网络】TCP的三次握手与四次挥手

    今天讲一下TCP的三次握手与四次挥手 1.首先说TCP 协议的特点:TCP是在不可靠的IP层之上实现的可靠的数据传输协议,它主要解决传输的可靠.有序.无丢失和不重复问题.TCP 是TCP/IP 体系中 ...

  3. 你应该这么理解TCP的三次握手和四次挥手

    前言: TCP协议是计算机的基础,他本身是一个非常非常复杂的协议. 本文只是蜻蜓点水,将从网络基础以及TCP的相关概念介绍开始,之后再将三次握手,四次挥手这些内容来阐述. 最后介绍一些常见问题,并给出 ...

  4. TCP 的三次握手和四次挥手

    参考资料: 1.TCP的三次握手与四次挥手理解及面试题: 2.Http协议三次握手和四次挥手: 3.TCP通信的三次握手和四次撒手的详细流程(顿悟) 前置: 序号(也称序列号) - Sequence ...

  5. TCP的三次握手与四次挥手

    TCP的三次握手与四次挥手 一.TCP(Transmission Control Protocol 传输控制协议) TCP是面向对连接,可靠的进程到进程通信的协议 TCP是提供全双工服务,即数据可在同 ...

  6. TCP/IP三次握手与四次挥手的正确姿势

    0.史上最容易理解的:TCP三次握手,四次挥手 https://cloud.tencent.com/developer/news/257281 A 理解TCP/IP三次握手与四次挥手的正确姿势http ...

  7. TCP的三次握手与四次挥手详解

    TCP的三次握手与四次挥手是TCP创建连接和关闭连接的核心流程,我们就从一个TCP结构图开始探究中的奥秘  序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序 ...

  8. TCP的三次握手与四次挥手笔记

    TCP的三次握手与四次挥手笔记 TCP Flags URG: 紧急指针标志 ACK:确认序号标志 PSH:push标志 RST:重置连接标志 SYN:同步序号,用于建立连接过程 FIN: finish ...

  9. TCP的三次握手与四次挥手理解及面试题

    TCP的三次握手与四次挥手理解及面试题(很全面) 转载自:https://blog.csdn.net/qq_38950316/article/details/81087809 本文经过借鉴书籍资料.他 ...

  10. WireShark抓包分析以及对TCP/IP三次握手与四次挥手的分析

    WireShark抓包分析TCP/IP三次握手与四次挥手 Wireshark介绍: Wireshark(前称Ethereal)是一个网络封包分析软件.功能十分强大,是一个可以在多个操作系统平台上的开源 ...

随机推荐

  1. CSS3 & Grid Layout All In One

    CSS3 & Grid Layout All In One W3C https://www.w3.org/TR/css-grid-1/ Grid Layout is a new layout ...

  2. how to get window width in javascript

    how to get window width in javascript how to get window width in js How to Detect Screen Resolution ...

  3. django学习-22.admi管理后台页面的文案展示等相关配置

    目录结果 1.前言 2.完整的操作步骤 2.1.第一步:对[settings.py]里的相关常量的值做如下修改 2.2.第二步:重启django项目[helloworld]的服务 2.3.第三步:重新 ...

  4. [Android搞机]修改build.prop解决类原生无法链接12、13信道wifi问题

    最近xda找包刷了个机,发现没法搜到12.13信道.所有未本地化的类原生都有此问题. root后打开/system/build.prop 可以用 在build.prop中加入以下几句,重启即可连接12 ...

  5. 维格表2月更新:智能图表上线,唤醒全量工作数据堪比AI

    你是否曾经想过,你的维格表数据有朝一日变化出如科幻电影般的数据图表? 你是否感到厌倦,对当前的后台系统密密麻麻的数据累觉不爱? 你是否一直期待,拥有一个专属大数据 BI 看板,让你的规划如有神助,挥斥 ...

  6. event loop整理

    宏任务和微任务 让我们从浏览器加载 script 说起,当浏览器加载完 script 之后,不考虑 script 标签的 defer 属性,script 将被立即执行.这时,我们就创建了一个宏任务. ...

  7. 剑指 Offer 65. 不用加减乘除做加法 + 位运算

    剑指 Offer 65. 不用加减乘除做加法 Offer_65 题目描述 题解分析 java代码 package com.walegarrett.offer; /** * @Author WaleGa ...

  8. CCF(JSON查询:40分):字符串+模拟

    JSON查询 201709-3 纯字符串模拟,考的就是耐心和细心.可惜这两样我都缺... #include<iostream> #include<cstdio> #includ ...

  9. 01_AlexNet

    torch.topk 功能:找出前k大的数据,及其索引号 input:张量 k:决定选取k个值,k=1是为top-1 dim:索引维度 返回: Tensor:前k大的值 LongTensor:前k大的 ...

  10. Java-for循环打印九九乘法表

    Java打印九九乘法表 public class forDemo04 { public static void main(String[] args) { //练习3:打印九九乘法表 /* 1*1=1 ...