网络编程实战
盛延敏
前大众点评云平台首席架构师
44207 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
网络编程实战
15
15
1.0x
00:00/00:00
登录|注册

19丨提高篇答疑:如何理解TCP四次挥手?

进入LAST_ACK状态
发送FIN包
调用close
进入CLOSED状态
进入TIME_WAIT状态
确认FIN包
接收对方的FIN包
读到EOF
进入CLOSE_WAIT状态
接收FIN包
进入FIN_WAIT_1状态
发送FIN包
打造高性能的网络程序框架
主动关闭读端的情况
SIGPIPE的作用
主动关闭后收到数据的情况
代码运行结果与时序图的对比
断开已连接的套接字
重新指定新的IP地址和端口号
服务器端通过sendto告知内核客户端地址和端口信息
服务器端通过recvfrom获取客户端地址和端口信息
报文发送的场景
删除原来记录的映射关系
记录目的地址和端口到套接字的映射关系
Linux 2.2后的语义变化
backlog参数的含义
已完成连接队列的大小
未完成连接队列的大小
Linux实际设置为30秒
RFC793规定为2分钟
TTL字段
TCP分组在网络中存活的最长时间
被动关闭方
主动关闭方
被动关闭方
主动关闭方
性能篇和实战篇
第11讲中程序和时序图的解惑
UDP套接字进行多次connect的操作
UDP中不进行connect时的数据收发
UDP连接和断开套接字的过程
listen函数中的backlog参数
MSL
TCP四次挥手
网络编程实战第19讲

该思维导图由 AI 生成,仅供参考

你好,我是盛延敏,这里是网络编程实战第 19 讲,欢迎回来。
这一篇文章是提高篇的答疑部分,也是提高篇的最后一篇文章。非常感谢大家的积极评论与留言,让每一篇文章的留言区都成为学习互动的好地方。在今天的内容里,我将针对大家的问题做一次集中回答,希望能帮助你解决前面碰到的一些问题。
这部分,我将采用 Q&A 的形式来展开。

如何理解 TCP 四次挥手?

TCP 建立一个连接需 3 次握手,而终止一个连接则需要四次挥手。四次挥手的整个过程是这样的:
首先,一方应用程序调用 close,我们称该方为主动关闭方,该端的 TCP 发送一个 FIN 包,表示需要关闭连接。之后主动关闭方进入 FIN_WAIT_1 状态。
接着,接收到这个 FIN 包的对端执行被动关闭。这个 FIN 由 TCP 协议栈处理,我们知道,TCP 协议栈为 FIN 包插入一个文件结束符 EOF 到接收缓冲区中,应用程序可以通过 read 调用来感知这个 FIN 包。一定要注意,这个 EOF 会被放在已排队等候的其他已接收的数据之后,这就意味着接收端应用程序需要处理这种异常情况,因为 EOF 表示在该连接上再无额外数据到达。此时,被动关闭方进入 CLOSE_WAIT 状态。
接下来,被动关闭方将读到这个 EOF,于是,应用程序也调用 close 关闭它的套接字,这导致它的 TCP 也发送一个 FIN 包。这样,被动关闭方将进入 LAST_ACK 状态。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文介绍了TCP四次挥手的重要概念,用于终止TCP连接。在四次挥手过程中,主动关闭方发送FIN包,被动关闭方接收并发送确认,最终完成连接的关闭。此外,文章还介绍了TCP连接的建立和断开过程,以及TCP和UDP的一些特性和使用方法。还解释了TCP中的backlog参数的含义和UDP中connect操作的作用。通过解答读者提出的问题,加深了对文章内容的理解。在性能篇和实战篇中,将会使用之前学到的知识,逐渐打造一个高性能的网络程序框架。这篇文章对于想要深入了解网络编程的读者来说,是一篇值得阅读的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《网络编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(28)

  • 最新
  • 精选
  • 安排
    MSL的值怎么和TTL对应的啊?比如MSL设置为30秒,那怎么计算出TTL的值呢?怎么保证一个报文在网络中真的存活不超过30秒?

    作者回复: TTL与MSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL。 设备在处理TTL的时候,是需要处理时间的,每次处理TTL时这个字段就都应该被减少,来反应花在处理报文上的时间。比如说处理了1秒减1,处理了2秒减2。这样就可以保证TTL为30的肯定活不过30秒。

    2019-09-13
    9
    20
  • Geek_f8c379
    signal(SIGPIPE, SIG_IGN); 实际上是忽略信号 而不是 按照默认的信号处理程序即退出

    作者回复: 因为你给SIGPIPE信号设置了SIG_IGN,所以是忽略信号。我说的是如果没有设置,默认的SIGPIPE处理的方式即为退出。

    2020-08-04
    6
  • 扩散性百万咸面包
    请问老师,SO_REUSEADDR虽说是重用TIME_WAIT的socket,为什么不能作为TIME_WAIT的解决方案呢?本质上是解决了端口占用问题,而TIME_WAIT的主要弊端不就在与端口占用吗?

    作者回复: 这是两个层面的东西,因为有了TIME_WAIT所以才导致不设置SO_REUSEADDR的服务端程序会出现"Address already in use"的错误,所以我们在服务端程序bind之前一定记得要设置SO_REUSEADDR。 但是TIME_WAIT本身还是很有价值的,TIME_WAIT 的引入是为了让 TCP 报文得以自然消失,同时为了让被动关闭方能够正常关闭。

    2020-04-22
    4
  • MSL 是任何 IP 数据报能够在因特网中存活的最长时间。其实它的实现不是靠计时器来完成的,在每个数据报里都包含有一个被称为 TTL(time to live)的 8 位字段,它的最大值为 255。TTL 可译为“生存时间”,这个生存时间由源主机设置初始值,它表示的是一个 IP 数据报可以经过的最大跳跃数,每经过一个路由器,就相当于经过了一跳,它的值就减 1,当此值减为 0 时,则所在的路由器会将其丢弃,同时发送 ICMP 报文通知源主机 这是否意味着一个IP数据报不可能经过255个路由器? 请问一个IP数据报经过多少路由器,这个由谁决定?怎么决定?和网络距离距离有什么关系? 😅感觉老师的回答和问题,没有完全的对上?

    作者回复: IP数据报经过多少路由器这个是无法确定的。

    2019-11-23
    4
  • 风羽星泉
    老师,我找到我提交的问题答案了。 使用 man listen 命令,可以找到下面这一句话: If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it is silently truncated to that value; 也就是说backlog 设置的值大于somaxconn,会被截断为somaxconn 的值。

    作者回复: 是的。

    2019-09-17
    2
  • 小蛋壳
    高性能的网络通信框架,是不是类似netty做的事?。那比如spring mvc或者其他任何应用程序框架其实底层都需要处理网络通讯这块。可以说知名的框架这块其实处理的都很好? java应用,是tomcat处理网络请求还是spring来处理的?还有nginx

    作者回复: netty是Java的网络通信框架,其底层实现还是依赖类似epoll的事件分发机制的。 spring mvc这类的使用的Java网络编程框架来做的,tomcat也是类似的。 Nginx是使用类似epoll的机制来自己实现的。

    2019-09-13
    2
  • 三年二班邱小东
    老师,为FIN包插入EOF的TCP协议栈是主动关闭方插入的,还是被动关闭方插入的?

    作者回复: 主动方。

    2022-02-25
    2
    1
  • 风羽星泉
    老师,我修改了程序中的backlog为10,/proc/sys/net/core/somaxconn没有变还是默认值128。测试程序同时发起800个连接请求,用netstat观察每次大概能建立10个连接,最后有大量连接报错“A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.”; 当我修改程序中的backlog为1000时,最大可连接数并没有突破128,最后也是报上面那个错误。 是不是backlog设置的值只能小于内核somaxconn的值,如果比它大,则取内核设置的值。

    作者回复: 因为你设置太大也没有,系统有个默认值。

    2019-09-17
    2
    1
  • 铲铲队
    至于已完成连接队列,如果声明的 backlog 参数比 /proc/sys/net/core/somaxconn 的参数要大,那么就会使用我们声明的那个值 -----》老师,这里是不是有问题呢,原文是这样的: If the backlog argument is greater than the value in /proc/sys/net/core/somaxconn, then it issilently truncated to that value 意思应该是设置的backlog值超过了最大值,则被截断为最大值把。

    作者回复: 字面意思应该是你说的那种。

    2022-04-23
  • GeekYanger
    记录一下,TIME_WAIT本身还是很有价值的,TIME_WAIT 的引入是为了让 TCP 报文得以自然消失,同时为了让被动关闭方能够正常关闭。

    作者回复: 👍

    2021-10-27
收起评论
显示
设置
留言
28
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部