上周有朋友去了字节面试,问到了TCP三次握手的问题,当时回答的不是很好,对于三次握手的发送的报文信息都不太熟,本文主要做一下总结和记录。

TCP全称为Transmission Control Protocol(传输控制协议),是一种面向连接的、可靠的、基于字节流的传输层通信协议。TCP也是全双工通信协议,表示客户端可以给服务端发送消息,服务端也可以向客户端发送消息。

报文

TCP处于ISO七层模型的传输层,传输层的单位是报文,报文信息如下:

Source port 和 Destination port

其中Source portDestination port分别代表发送端口接收端口。两个不同机器上的进程通信,需要通过端口和IP协议中的IP标识唯一的进程。

Sequence number 和 Acknowledgment number

Sequence number表示序列号,表示要发送数据的起始号,在下面的三次握手使用seq表示,Acknowledgment number表示确认号,返回确认号,表示消息已经接收,返回下次要发送的起始号。在下面的三次握手使用ackNum标识。

TCP flag

TCP flag表示TCP标志位,主要介绍两个ACKSYN

  • SYN同步序号,用于建立连接过程。
  • ACK确认序号标识,标识表示发送信息已确认接收。

Windows Size

TCP使用滑动窗口来实现流量控制,根据窗口大小,确认要发送数据包的个数。

TCP 三次握手

TCP三次握手,是指建立一个TCP连接时,需要客户端和服务器总共发送3个包。三次握手的目的是连接服务指定端口,建立 TCP 连接,并确认连接双方的序列号确认号,确认TCP窗口大小信息。

三次握手详解:

  • 第一次握手 SYN=1,seq=x

    • 客户端发送一个TCPSYN标志位为1的包,指定客户端连接的服务器端口,初始序列号seqx。发送完毕之后客户端进入SYN_SEND
  • 第二次握手 SYN=1,ACK=1,seq=y,ACKnum=x+1
    • 服务器发回确认包ACK应答。即SYN标志位和ACK标志位均为1。服务器端发送序列号seqy,同时将确认序号ackNum设置为客户端的序列号seq+1ackNum表示要下次要发送数据包序列号的起始值。发送完毕后,服务端进入SYN_SEND状态。
  • 第三次握手 ACK=1,ACKnum=y+1
    • 客户端再次发送确认包ACK,ACK 标志位为1,并且把服务器发来的ackNum作为起始序号seq发送给服务端,确认号ackNum为服务端发送的序列号+1也就是y+1,放在确认字段中发送给对方,
    • 发送完毕后,客户端进入ESTABLISHED状态,当服务器端接收到这个包时,也进入ESTABLISHED状态,开始数据传输。

wireshake 抓包

为了更好理解三次握手,使用wireshakej进行抓包。首先请求访问链接,TCP三次握手对应下面编号576364:

  • 第一步:192.168.5.150 ----> 47.98.202.133 [SYN] seq=0
  • 第二步:47.98.202.133 ----> 192.168.5.150 [SYN ACK] seq=0 ack=1
  • 第三步:192.168.3.150 ----> 47.98.202.133 [ACK] seq=1 ack=1

记忆口诀

那么在面试的时候应该如何记忆三次握手的流程?三次握手是为了建立连接,其中主要是为了确认客户端和服务端的序列号seq,那么确认序列号就需要接收方返回序列号,来确保自己发送的序列号能成功发送。

  • 第一次握手和第二次握手确保客户端的序列号,所以第一次发送seq,第二次返回ack,当接收到返回信息,表明确认了客户端序列号。第一次和第二次都是建立连接过程,所以都带有SYN标记位。而第二次返回号,所以第二次带ACK标志位。
  • 第一次发送了序号seqx,返回确认号ackNumx+1,因为发送消耗了一个序号,所以ackNum要加1
  • 第二次握手和第三次握手是为了确保服务端的序列号,服务端发送序列号seq,客户端返回确认号ackNum,值为seq+1。第二次握手要发送序号和返回上一次的握手的确认号,所以第二次握手带有SYNACK标志位。并且要发送序列号seq和确认号ackNum。第三次握手是确认服务端发送序列号,所以带有标志位ACK,返回确认号ackNum

为啥 TCP 需要三次握手,不是两次,四次

TCP三次握手是为了确认双方的序列号,这就像一个发送—应答机制,客户端发序列号,服务端返回确认号,此时确认了客户端的序列号。如果是两次握手,只能确认客户端的序列号,无法确认服务端的序列号。三次握手是确认两个序列号最小的连接次数。四次也可以,但是没有必要,需要减少握手的次数,加快连接速度。

总结

  • 本文先介绍了报文头信息,三次握手主要用到了:

    • 序列号seq,确认号ackNum
    • TCP标记位,SYN同步序号,表示建立连接过程。ACK确认序号标识,标识表示发送信息已确认接收
  • 三次握手详解:
    • 第一次握手,客户端发送带有SYN标记位的包,带有初始化序列号x,发送完毕客户端进入SYN_SEND状态。
    • 第二次握手,服务端返回应答标记位ACK,并返回确认号ackNumx+1,x+1表示发送消耗了一个序列号。返回了确认号表示确认了客户端序列号。服务端也要发送序列号y,所以也要带有SYN的标记位。
    • 第三次握手客户端发送确认包ackNumy+1,所以带确认序号标志ACK。建立连接,发送序号x+1,开始传输数据。

参考

TCP协议

字节一面:说说TCP的三次握手的更多相关文章

  1. 简析TCP的三次握手与四次分手

    TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续.它只是一个超级麻烦的协议,而它又是互联网的基础,也 ...

  2. TCP的三次握手(建立连接)和四次挥手(关闭连接)

    参照: http://course.ccniit.com/CSTD/Linux/reference/files/018.PDF http://hi.baidu.com/raycomer/item/94 ...

  3. 简析TCP的三次握手与四次挥手

    TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文章时,我想你也知道TCP的概念了,想要更深入的了解TCP的工作,我们就继续.它只是一个超级麻烦的协议,而它又是互联网的基础,也 ...

  4. 简析TCP的三次握手与四次分手【转】

    转自 简析TCP的三次握手与四次分手 | 果冻想http://www.jellythink.com/archives/705 TCP是什么? 具体的关于TCP是什么,我不打算详细的说了:当你看到这篇文 ...

  5. 【转载】简析TCP的三次握手与四次分手

    最近在补习HTTP协议相关知识点,看到这篇讲得不错,所以转载收藏一下,同时也分享给大家.原文地址:http://www.jellythink.com/archives/705,版权归原作者所有. TC ...

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

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

  7. TCP的三次握手与四次挥手(个人总结)

    序列号seq:占4个字节,用来标记数据段的顺序,TCP把连接中发送的所有数据字节都编上一个序号,第一个字节的编号由本地随机产生:给字节编上序号后,就给每一个报文段指派一个序号:序列号seq就是这个报文 ...

  8. 在深谈TCP/IP三步握手&四步挥手原理及衍生问题—长文解剖IP

    如果对网络工程基础不牢,建议通读<细说OSI七层协议模型及OSI参考模型中的数据封装过程?> 下面就是TCP/IP(Transmission Control Protoco/Interne ...

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

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

随机推荐

  1. Java 泛型中的通配符

    本文内容如下: 1. 什么是类型擦除 2.常用的 ?, T, E, K, V, N的含义 3.上界通配符 < ?extends E> 4.下界通配符 < ?super E> 5 ...

  2. 关于Vue的几个实用知识点(持续更新中……)

    前言 排名不分先后,按自己习惯来的. 一.provide.inject 高级组件 总述: provide在父组件中定义,inject 在子孙组件中定义. provide:选项应该是一个对象或返回一个对 ...

  3. MYSQL的事务和索引

    事务 什么是事务 事务就是将一组SQL语句放在同一批次内去执行 如果一个SQL语句出错,则该批次内的所有SQL都将被取消执行 MySQL事务处理只支持InnoDB和BDB数据表类型 事务的ACID原则 ...

  4. Python:socket编程教程

    ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...

  5. Timer和ScheduledThreadPoolExecutor的区别

    Timer 基于单线程.系统时间实现的延时.定期任务执行类.具体可以看下面红色标注的代码. public class Timer { /** * The timer task queue. This ...

  6. NC14326 Rails

    NC14326 Rails 题目 题目描述 There is a famous railway station in PopPush City. Country there is incredibly ...

  7. HashMap源码深度剖析,手把手带你分析每一行代码,包会!!!

    HashMap源码深度剖析,手把手带你分析每一行代码! 在前面的两篇文章哈希表的原理和200行代码带你写自己的HashMap(如果你阅读这篇文章感觉有点困难,可以先阅读这两篇文章)当中我们仔细谈到了哈 ...

  8. 如何创建一个带诊断工具的.NET镜像

    现阶段的问题 现在是云原生和容器化时代,.NET Core对于云原生来说有非常好的兼容和亲和性,dotnet社区以及微软为.NET Core提供了非常方便的镜像容器化方案.所以现在大多数的dotnet ...

  9. 方法引用_通过this引用本类的成员方法和方法引用_类的构造器(构造方法)引用和数组的构造器引用

    package com.yang.Test.ThisMethodReference; /** * 通过this引用本类的成员方法 */ public class Husband { //定义一个买房子 ...

  10. maven项目(引入依赖失败, pom.xml 报错\爆红)

    引入项目过程中,idea引入磁盘的某个的maven项目 这里以springboot项目以例子,发现pom.xml 的依赖大面积爆红,springboot的版本依赖也报错了,然后发现下面有进度条在下载, ...