TCP三次握手、四次挥手

2023-05-16

TCP通信流程

TCP和UDP

TCP和UDP区别如下:

  • UDP:用户数据报文协议,面向无连接,可以单播,多播,广播,面向数据报,不可靠。
  • TCP:传输控制协议,面向连接,可靠的,基于字节流的,仅支持单播。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pG33Qqco-1659703867233)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659699991269.png)]

TCP的通信流程

①服务器端 (被动接受连接的角色)

  1. 创建一个用于监听的套接字

    • 监听:监听有客户端的连接
    • 套接字:这个套接字其实就是一个文件描述符
  2. 将这个监听文件描述符和本地的IP和端口绑定(IP和端口就是服务器的地址信息)

    • 客户端连接服务器的时候使用的就是这个IP和端口
  3. 设置监听,监听的fd开始工作

  4. 阻塞等待,当有客户端发起连接,解除阻塞,接受客户端的连接,会得到一个和客户端通信的套接字(fd)

  5. 通信

    • 接收数据
    • 发送数据

6.通信结束,断开连接

②客户端(主动连接角色)

  1. 创建一个用于通信的套接字(fd)
  2. 连接服务器,需要指定连接的服务器的 IP 和 端口
  3. 连接成功了,客户端可以直接和服务器通信
    • 接收数据
    • 发送数据
  4. 通信结束,断开连接

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BIhIpskO-1659703867234)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659699815623.png)]

基本概念

TCP是一种面向连接的单播协议,在发送数据前,通信双方必须在彼此间建立一条连接。所谓“连接”,其实是客户端和服务器的内存里保存的一份关于对方的信息,如IP地址、端口号等。

TCP可以看成是一种字节流,它会处理IP层或以下层的丢包、重复及错误问题。在连接的建立过程中,双方需要交换一些连接的参数。这些参数可以放在TCP头部。

TCP提供了一种可靠、面向连接、字节流、传输层的服务,采用三次握手建立一个连接。采用四次挥手关闭一个连接。

三次握手目的是保证双方互相之间建立了连接

三次握手发生在客户端连接的时候,当叼用connect()的时候,底层会通过TCP协议进行三次握手。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CQcsr5zp-1659703867235)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659676103742.png)]

TCP传送的数据单元称为报文段。TCP报文段既可以用来 运载数据,又可以用来建立连接、释放连接和应答。TCP报文段分为TCP头部和数据两个部分。

TCP头部需要掌握以下几种信息:

  • 32位序号(seq):由于TCP连接传送的数据是面向字节流的(逐个字节传送的),所以为了保证传送数据的完整性和顺序性,TCP连接传送的每个字节都按顺序编号序号字段的值指的是本报文段传送的数据的第一个数据字节的序号。 如:一个报文段所发送的数据的序号值是301,携带的数据有100B,那么本报文段数据的最后一个字节序号是400,因此下一个报文段发送的数据的序号应该从401开始。

  • 32位确认号(ack):期望收到对方下一个报文段的第一个数据字节的序号。若确认号为N,表明到序号N-1为止的数据都已经正确收到,并且期望收到序号为N的报文段序号。

  • ACK:表示确认号是否有效。我们称携带ACK标志的TCP报文段为确认报文段。建立连接后所有发送的报文ACK都置为1.

  • SYN:表示请求建立连接。我们称携带SYN标志的TCP报文段成为复位报文段。

  • FIN:表示通知对方本端要关闭连接了。我们称携带FIN标志的TCP报文段称为结束报文段。

  • 16位窗口大小:是TCP流量控制的一个手段。这里说的窗口,指的是接收通告窗口。它告诉对方本端的TCP接收缓存中还能容纳多少个字节的数据,这样对方可以控制发送数据的速度。

TCP三次握手

三次握手过程

三次握手过程如下:

  1. 第一次握手:
    • 客户端将SYN标志位置为1
    • 生成一个随机的32位序号x
    • 这个序号后面可以携带数据(数据的大小)
  2. 第二次握手:
    • 服务器端接收客户端的连接:ACK = 1
    • 服务器回发一个确认序号:ack = 客户端的序号(x) + 数据长度 + SYN/FIN(当做一个字节算)
    • 服务器端会向客户端发起连接请求:SYN = 1
    • 服务器会生成一个随机信号:seq = y
  3. 第三次握手
    • 客户端应答服务器端连接请求:ACK = 1
    • 客户端回复收到了服务器端的数据:ack = 服务器端序号(y) + 数据长度 + SYN/FIN

简易理解版本的三次握手过程图如下:(省略序号和确认号)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MXnn9hzE-1659703867235)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659677595090.png)]

完整版三次握手的过程时序图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tmAxw1ZQ-1659703867236)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659682685556.png)]

例如:客户端给服务器端发送数据的过程如下图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fyyEuV23-1659703867237)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659684552483.png)]

为什么需要三次握手?

因为客户端要确认自己是否能发送和接收数据,服务端也要确认自己能否发送和接收数据。如果客户端只能发送数据不能接收数据,采用两次握手的话,流程如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0kK4Lg4S-1659703867238)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659677875175.png)]

客户端只能发送数据不能接收数据,但2次握手便建立了连接,这种建立的连接显然是不可靠的。而三次握手可以确认客户端和服务器端收、发数据都正常才建立可靠的连接。

TCP四次挥手

四次挥手发生在断开连接的时候,在程序中当调用了close()会使用TCP协议进行四次挥手。

客户端和服务器端都可以主动发起断开连接,谁先调用close()谁就是发起。

因为TCP连接的时候,采用三次握手建立的连接是双向的,在断开的时候需要双向断开。

四次挥手的过程

简单理解版本四次挥手图如下:

例如:客户端请求断开连接(服务器端也可以请求断开连接,过程一样)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K92C3cXa-1659703867239)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659698464511.png)]

完整版四次挥手的过程时序图如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-toMFzOFj-1659703867239)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659699388842.png)]

为什么需要四次挥手,而不是直接关停程序

因为建立连接的时候通信双方会保存各自的信息(ip、端口等),断开连接后应该把这些信息销毁掉,否则这些信息一直存在系统当中,会造成内存泄漏问题。

TCP滑动窗口

流量控制:控制发送方发送速度太快,超出接收方缓冲区的大小。

拥塞控制:使用网络带宽主机太多,导致整个网络发送缓慢、排队时间过长而出现拥塞。

滑动窗口是一种流量控制技术。早期的网络通信中,通信双方不会考虑网络的拥挤情况,直接发送数据。由于大家不知道网络拥塞状况,同时发送数据,导致中间节点阻塞掉包,谁也发不了数据,所以就有了滑动窗口机制来解决此问题。滑动窗口协议是用来改善吞吐量的一种技术,即容许发送方在接受任何应答之前传送附加的包。接收方告诉发送方在某一时刻能送多少包(称窗口尺寸)。

TCP中采用滑动窗口机制来进行传输控制,,滑动窗口的大小意味着接收方还有多大的缓冲区可以用于接收数据。 发送方可以通过滑动窗口的大小来确定应该发送多少字节的数据。当滑动窗口为0时,发送方一般不能再发送数据报。

滑动窗口是TCP中实现诸如ACK确认、流量控制、拥塞控制的承载结构。

滑动窗口可以理解为一块缓冲区,窗口理解为缓冲区的大小。

滑动窗口的大小会随着发送数据和接收数据而变化。通信双方都有发送缓冲区和接收数据的缓冲区。

  • 服务器:
    • 发送缓冲区:(发送缓冲区的窗口)
    • 接收缓冲区:(接收缓冲区的窗口)
  • 客户端:
    • 发送缓冲区:(发送缓冲区的窗口)
    • 接收缓冲区:(接收缓冲区的窗口)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5oCYnhZt-1659703867240)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659687783067.png)]

每一时刻,接收方给发送方发送的TCP报文段中的信息会包含接收方剩余缓冲区的大小,每次发送方发送数据的大小不能超过剩余缓冲区的大小,如果剩余缓冲区为0,则发送方停止发送数据。

例:发送端发送速度比接收端接收速度快,利用滑动窗口来进行流量控制的过程如下图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Yw6xw0zv-1659703867240)(C:\Users\84995\AppData\Roaming\Typora\typora-user-images\1659690160601.png)]

  1. 第一次握手:客户端向服务器发起连接,客户端的滑动窗口为4096,一次发送的最大数据量为1460.
  2. 第二次握手:服务器端接收连接情况,告诉客户端服务器窗口大小为6144,一次发送的最大数据量为1024.
  3. 第三次握手:向服务器端发送确认,成功建立起TCP连接。
  4. 4~9,客户端连续给服务器发送了6k的数据,每次发送1k
  5. 第10次,服务器告诉客户端发送的6k数据已经接收到,存储在缓冲区中,缓冲区数据已经处理了2k,窗口大小是2k
  6. 第11次,服务器告诉客户端发送的6k数据已经接收到,存储在缓冲区中,缓冲区数据已经处理了4k,窗口大小是4k
  7. 第12次,客户端给服务器发送了1k的数据
  8. 第13次,第一次挥手,客户端主动请求和服务器断开连接,并且给服务器发送了1k的数据
  9. 第14次,第二次挥手,服务器回复ack8194,同意断开连接的请求,告诉客户端已经接受到刚才2k的数据,并告诉窗口大小为2k
  10. 第15、16次,通知客户端滑动窗口的大小
  11. 第17次,第三次挥手,服务器端给客户端发送FIN,请求断开连接。
  12. 第18次,第四次挥手,客户端换同意了服务器端的断开请求,断开连接。

资料:https://www.nowcoder.com/study/live/504/4/17

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP三次握手、四次挥手 的相关文章

  • re.sub()用法详解

    源代码 参数及其意义 xff1a def sub pattern repl string count 61 0 flags 61 0 34 34 34 Return the string obtained by replacing the
  • BERT模型的详细介绍

    1 BERT 的基本原理是什么 xff1f BERT 来自 Google 的论文Pre training of Deep Bidirectional Transformers for Language Understanding xff0c
  • 自然语言处理(NLP)之使用TF-IDF模型计算文本相似度

    自然语言处理 NLP 之使用TF IDF模型计算文本相似度 所用数据集 xff1a ChnSentiCorp htl all csv 语料库即存放稀疏向量的列表 要注意的是 xff0c 搜索文本text与被检索的文档共用一个特征词词典 NL
  • C++中关于类重复定义的分析和解决方法

    在C 43 43 中将类以及类中的成员函数的声明放在 h的头文件中 xff0c 而将类中成员函数的定义 xff08 即实现代码 xff09 放在 cpp的源文件中 xff0c 这样我们的程序设计起来更加的模块化 xff0c 但是 xff0c
  • re.search()用法详解

    re search xff1a 匹配整个字符串 xff0c 并返回第一个成功的匹配 如果匹配失败 xff0c 则返回None pattern 匹配的规则 string 要匹配的内容 flags 标志位 这个是可选的 就是可以不写 可以写 比
  • re.findall()用法详解

    re findall xff1a 函数返回包含所有匹配项的列表 返回string中所有与pattern相匹配的全部字串 xff0c 返回形式为数组 示例代码1 xff1a 打印所有的匹配项 import re s 61 34 Long li
  • Linux系统中创建虚拟环境详解

    1 方法一 1 1 安装虚拟环境的命令 xff1a sudo pip install virtualenv sudo pip install virtualenvwrapper 1 2 安装完虚拟环境后 xff0c 如果提示找不到mkvir
  • 使用python将图片改为灰度图或黑白图

    使用python将图片改为灰度图或黑白图有三种方式 xff0c 分别是是使用cv2库和PIL库来实现 xff0c 详细过程如下所示 1 使用cv2库将图片改为灰度图 在使用cv2进行读取原彩色图片时 xff0c 在里面添加一个参数cv2 I
  • 虚拟机中windows镜像下载与安装

    镜像文件下载 xff1a 链接 xff1a https pan baidu com s 1VKWMHHCGRwWXk2GpxyUp0A 提取码 xff1a shlg 注意 xff1a 虚拟机中的镜像和本地电脑系统安装的镜像是一样的 安装教程
  • mongo数据库中字符串型正负数值比较大小

    数据库中数据展示 xff1a 使用python代码实现 xff1a Requires pymongo 3 6 0 43 from pymongo import MongoClient client 61 MongoClient 34 mon
  • flask项目中内部接口调用其他内部接口操作

    1 requests 在 Flask 框架项目中 xff0c 可以通过使用 requests 模块来进行内部接口调用 requests 模块是 Python 中常用的 HTTP 请求库 xff0c 可以用于发送 HTTP 请求和处理响应 示
  • ElasticSearch删除索引中的数据(delete_by_query)

    1 删除两个月以前的数据 在 Elasticsearch 中 xff0c 要删除两个月以前的数据 xff0c 可以通过以下步骤 xff1a 计算当前时间的两个月前的日期 xff0c 可以使用 Python 的 datetime 模块来实现
  • Qt Creator子图绘制

    Qt中在一个窗体文件内画所有图显然是不好维护的 xff0c 我们可以将主窗体拆分为几个子窗体 xff0c 在子窗体中绘制子图 xff0c 这样便于我们去维护我们的代码 1 在工程文件中右键 gt Add New 2 选择Qt 设计师界面 3
  • MessageFilter [target=odom ]: Dropped 100.00% of messages so far.问题解决

    错误提示 WARN 1580994954 426403779 MessageFilter target 61 odom Dropped 100 00 of messages so far Please turn the ros gmappi
  • 电磁循迹智能车基于stm32cubeMX、HAL库—我的第一辆智能车

    我的第一辆智能车 电磁循迹智能车 提示 本文适用于初学 想完成一个基础四轮车练练手者 大佬还请勿喷 不过欢迎提出意见 有纰漏之处我将及时纠正 注 工程代码链接已贴在文末 前言 所用到的硬件平台 stm32f103c8t6 舵机 电机 L29
  • 2022年国赛建模B题思路与程序

    B题 无人机遂行编队飞行中的纯方位无源定位 关键词搜索 xff1a 无人机 xff0c 无源定位 其实这个工作特别多 xff0c 知网一堆 xff0c 如果选这个题一定要想好做的出彩 xff0c 另外网上的场景和本题不是很一样 xff0c
  • 2017全国大学生电子设计竞赛:室内可见光定位装置

  • 基于FreeRTOS下多任务的同时操作

    FreeRTOS移植及多任务的实现 前言 xff1a 一 FreeRTOS移植 xff08 1 xff09 移植准备工作 xff08 2 xff09 FreeRTOS移植到stm32中 xff08 3 xff09 例程验证 二 多任务实现
  • undefined symbol 问题解决记录

    历经一个月 xff0c 昨日完成打印机network部分的编写 c语言 xff0c 编写makefile构建动态库 构建完成后遂进行调用测试 xff0c 出现 xff1a network symbol lookup error usr li
  • 2.O(NlogN)的排序算法

    认识O NlogN 的排序算法 1 剖析递归行为及其时间复杂度的估算 递归过程 xff1a 递归过程是一个多叉树 xff0c 计算所有树的结点的过程就是利用栈进行后序遍历 xff0c 每个结点通过自己的所有子结点给自己汇总信息之后才能继续向

随机推荐

  • 4.二叉树的遍历(C++版)

    二叉树的递归 1 二叉树递归遍历 二叉树的递归序 递归序过程 xff1a 两个注释1之间的代码代表第一次来到一个节点的时候 xff0c 会判断一下这个节点是否为空 xff1b 来到这个节点的左树去遍历 遍历完第二次回到本函数 xff0c 进
  • 6.暴力递归转动态规划

    动态规划 1 什么是动态规划 xff1f 动态规划就是暴力递归 xff08 回溯 xff09 的过程中有重复调用的过程 xff0c 动态规划在算过每次调用后把答案记下来 xff0c 下次再遇到重复过程直接调用这个行为就叫动态规划 动态规划就
  • 8.岛问题

    岛问题 题目 一个矩阵中只有0和1两种值 xff0c 每个位置都可以和自己的上 下 左 右四个位置相连 xff0c 如果有一片1连在一起 xff0c 这个部分叫做一个岛 xff0c 求一个矩阵中有多少个岛 xff1f 例子 0 0 1 0
  • 9.KMP算法

    KMP算法 1 KMP算法解决的问题 字符串str1和str2 xff0c str1是否包含str2 xff0c 如果包含返回str2在str1中开始的位置 xff0c 如果不包含返回 1 如果做到时间复杂度O N 完成 xff1f 测试用
  • 10.Manacher算法(用于解决回文子串问题)

    Manacher算法 1 Manacher算法解决的问题 字符串str中 xff0c 最长回文子串的长度如何求解 xff1f 如何做到时间复杂度O N 完成 xff1f 回文序列是从左往右和从右往左看一样 xff0c 如abba xff0c
  • git push代码到远程仓库,报错解决:fatal: unable to access ‘https://github.com/.......‘: OpenSSL SSL_read: Connec

    报错如下 xff1a 产生原因 xff1a 一般是这是因为服务器的SSL证书没有经过第三方机构的签署 xff0c 所以才报错解除ssl验证后 xff0c 再次git即可 解决办法输入此条git命令 xff1a git config glob
  • 11.滑动窗口的最大值——重要结构双端队列

    滑动窗口最大 xff08 小 xff09 值 1 滑动窗口最大值结构 窗口概念 xff1a 一开始窗口左边界L 有边界R都停留在数组左侧 xff0c 窗口L和R都只能往数组右边移动 xff0c 并且左边界L永远不能超过有边界R 任何时刻都能
  • 12.单调栈——解决接雨水和柱状图中的最大矩形等问题

    单调栈 1 单调栈实现结构 单调栈解决的问题 xff1a 给你一个数组 想要用尽可能低的代价知道数组中每一个元素的左边元素比它大的或者右边元素比他大的信息是什么 如果用暴力方法 xff0c 左边遍历一次右边遍历一次 xff0c 时间复杂度为
  • 12.快速排序

    1荷兰国旗问题 问题1 xff1a 给定一个数组arr和一个数num xff0c 将小于等于num的数放在数组的左边大于num的数放在数组的右边 xff08 不要求有序 xff09 要求额外空间复杂度为O 1 时间复杂度为O N 遍历数组元
  • 死锁预防、死锁避免、死锁检测

    死锁 1 死锁的概念 1 1死锁的定义 多个进程并发执行 xff0c 由于竞争资源而造成的一种僵局 xff08 互相等待 xff09 xff0c 若无外力作用 xff0c 这些进程都将无法推进 xff0c 这就是死锁现象 例如 xff1a
  • 内存分配方式

    内存分配方式 1 基本概念 内存管理的基本概念 虽然计算机硬件发展 xff0c 内存容量在不断变大 xff0c 但是也不可能将所有用户进程和系统所需要的程序和数据放入内存中 xff0c 因此操作系统必须要对内存空间进行合理划分和有效动态分配
  • 虚拟内存和LRU页面置换算法

    虚拟内存 1 虚拟内存的基本概念 传统存储管理方式的特征 传统的内存管理策略都是为了同时将多个进程保存进内存中 xff0c 它们具有以下的共同特征 xff1a 一次性 作业必须一次性全部装入内存后 xff0c 才能开始运行 xff08 静态
  • 0.0C++和C的区别

    C 43 43 和C的区别 C 43 43 如今是一个同时支持面向过程 面向对象 函数形式 泛型形式 元编程形式的语言 我们该如何理解C 43 43 这门语言呢 xff1f Effective C 43 43 书中给出了一个简单的方法 xf
  • 15.9为什么要将成员变量设置为private

    为什么要将成员变量声明为private 为什么要将成员变量封装为private xff0c 主要有以下四个原因 xff1a 好处1 xff1a 如果成员变量不是public xff0c 那么客户唯一能访问成员变量的唯一方式就是通过成员函数
  • 2.7.C++中static关键字的5种基本用法

    static关键字 static关键字主要应用于以下几种情况 xff1a 情况1 xff1a static静态函数 定义静态函数 xff1a 在函数返回类型前加上static关键字 xff0c 函数即被定义为静态函数 静态函数只能在本源文件
  • 进程调度算法

    进程调度 在多道程序系统中 xff0c 进程数量往往多于处理机的个数 xff0c 因此进程竞争使用处理机的情况在所难免 处理机调度是对处理机进行分配 xff0c 即从就绪队列中按照一定的算法选择一个进程并将处理机分配给它运行 xff0c 以
  • git clone 出现fatal: unable to access ‘https://github 类错误解决方法

    git clone 遇到问题 xff1a fatal unable to access https github comxxxxxxxxxxx Failed to connect to xxxxxxxxxxxxx 问题 将命令行里的http
  • 进程通信的方式

    进程通信 1 进程通信的概念 进程是一个独立的资源分配单元 xff0c 不同进程 xff08 主要是指不同的用户进程 xff09 之间的资源是独立的 xff0c 没有关联的 xff0c 不能在一个进程中直接访问另一个进程的资源 但是 xff
  • 网络通信的过程

    网络通信的过程 封装 上层协议时如何使用下层协议提供的服务的呢 xff1f 其实这是通过封装实现的 应用程序是在发送到物理网络上之前 xff0c 将沿着协议栈从上往下依次传递 每层协议都将在上层数据的基础上加上自己的头部信息 xff08 有
  • TCP三次握手、四次挥手

    TCP通信流程 TCP和UDP TCP和UDP区别如下 xff1a UDP xff1a 用户数据报文协议 xff0c 面向无连接 xff0c 可以单播 xff0c 多播 xff0c 广播 xff0c 面向数据报 xff0c 不可靠 TCP