网络编程实战
盛延敏
前大众点评云平台首席架构师
立即订阅
6034 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 学好网络编程,需要掌握哪些核心问题?
免费
第一模块:基础篇 (9讲)
01 | 追古溯源:TCP/IP和Linux是如何改变世界的?
02 | 网络编程模型:认识客户端-服务器网络模型的基本概念
03丨套接字和地址:像电话和电话号码一样理解它们
04 | TCP三次握手:怎么使用套接字格式建立连接?
05 | 使用套接字进行读写:开始交流吧
06 | 嗨,别忘了UDP这个小兄弟
07 | What? 还有本地套接字?
08 | 工欲善其事必先利其器:学会使用各种工具
09丨答疑篇:学习网络编程前,需要准备哪些东西?
第二模块:提高篇 (10讲)
10 | TIME_WAIT:隐藏在细节下的魔鬼
11 | 优雅地关闭还是粗暴地关闭 ?
12 | 连接无效:使用Keep-Alive还是应用心跳来检测?
13 | 小数据包应对之策:理解TCP协议中的动态数据传输
14丨UDP也可以是“已连接”?
15 | 怎么老是出现“地址已经被使用”?
16 | 如何理解TCP的“流”?
17 | TCP并不总是“可靠”的?
18 | 防人之心不可无:检查数据的有效性
19丨提高篇答疑:如何理解TCP四次挥手?
期中复习周 (2讲)
期中大作业丨动手编写一个自己的程序吧!
免费
期中大作业丨题目以及解答剖析
免费
第三模块:性能篇 (12讲)
20 | 大名⿍⿍的select:看我如何同时感知多个I/O事件
21 | poll:另一种I/O多路复用
22 | 非阻塞I/O:提升性能的加速器
23 | Linux利器:epoll的前世今生
24 | C10K问题:高并发模型设计
25 | 使用阻塞I/O和进程模型:最传统的方式
26 | 使用阻塞I/O和线程模型:换一种轻量的方式
27 | I/O多路复用遇上线程:使用poll单线程处理所有I/O事件
28 | I/O多路复用进阶:子线程使用poll处理连接I/O事件
29 | 渐入佳境:使用epoll和多线程模型
30 | 真正的大杀器:异步I/O探索
31丨性能篇答疑:epoll源码深度剖析
第四模块:实战篇 (4讲)
32 | 自己动手写高性能HTTP服务器(一):设计和思路
33 | 自己动手写高性能HTTP服务器(二):I/O模型和多线程模型实现
34 | 自己动手写高性能HTTP服务器(三):TCP字节流处理和HTTP协议实现
35 | 答疑:编写高性能网络编程框架时,都需要注意哪些问题?
结束语 (1讲)
结束语丨我相信这不是结束,让我们江湖再见
网络编程实战
登录|注册

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

盛延敏 2019-09-13
你好,我是盛延敏,这里是网络编程实战第 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/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《网络编程实战》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(12)

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

    作者回复: TTL与MSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL。

    设备在处理TTL的时候,是需要处理时间的,每次处理TTL时这个字段就都应该被减少,来反应花在处理报文上的时间。比如说处理了1秒减1,处理了2秒减2。这样就可以保证TTL为30的肯定活不过30秒。

    2019-09-13
    2
    6
  • 风羽星泉
    老师,我找到我提交的问题答案了。 使用 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
    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
    1
  • 安排
    对于udp那里,connect的作用应该是记录服务端ip,端口号和socket的对应关系吧

    作者回复: 是的。

    2019-09-13
    1
  • godtrue
    MSL 是任何 IP 数据报能够在因特网中存活的最长时间。其实它的实现不是靠计时器来完成的,在每个数据报里都包含有一个被称为 TTL(time to live)的 8 位字段,它的最大值为 255。TTL 可译为“生存时间”,这个生存时间由源主机设置初始值,它表示的是一个 IP 数据报可以经过的最大跳跃数,每经过一个路由器,就相当于经过了一跳,它的值就减 1,当此值减为 0 时,则所在的路由器会将其丢弃,同时发送 ICMP 报文通知源主机

    这是否意味着一个IP数据报不可能经过255个路由器?
    请问一个IP数据报经过多少路由器,这个由谁决定?怎么决定?和网络距离距离有什么关系?

    😅感觉老师的回答和问题,没有完全的对上?

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

    2019-11-23
  • fl260919784
    应用程序如何模拟三次挥手关闭一条tcp连接(一般情况下是fin,ack,fin,ack,但也存在fin,ack+fin,ack)

    作者回复: 还真不好模拟,这个直接通过程序来实现比较方便,比如shutdown、close。

    2019-10-13
  • 码农Kevin亮
    请问老师,为什么四次挥手中,被动关闭方不能把ack与fin合并呢

    作者回复: 好问题,我好想看过有类似的优化手段,实际上是不是这样做的,我不敢保证,可能要去读源码了。

    2019-09-23
    3
  • kabuka
    “这个 EOF 会被放在已排队等候的其他已接收的数据之后,这就意味着接收端应用程序需要处理这种异常情况“ 這種情況不屬於正常嗎? EOF按照順序排在隊列最後面,在處理完隊列前面的消息后,在處理EOF,正常結束。老師說的需要處理異常情況是指什麼?
     

    作者回复: 哦,我的意思是EOF作为一个异常情况,需要加以处理,也就是读到返回值为0的情况。确实如你所言,程序的逻辑是正常处理的。

    2019-09-19
  • 灰色
    即使经过了2MSL也不一定保证一个tcp分组的TTL为0吧,也就是这个分组变得无效,那么TIME_WAIT如何避免连接“化身”的问题呢?

    作者回复: 要保证的,一般来说MSL不等于TTL,MSL要比TTL大,保证2MSL的时间时候对应的分组一定变得无效。

    2019-09-15
  • 传说中的成大大
    今天又回头讲udp的connect突然想起来 那udp的send是个广播操作?

    作者回复: 不是啊,如果对着一个广播地址发送,才是一个广播操作。

    2019-09-15
  • 沉淀的梦想
    实验了一下往半关闭(本端shutdown)状态的连接里写东西,发现不会返回任何错误信息,,感觉就像正常的连接write一样(然它写多少字节,它就返回多少),这个是为什么呢?

    作者回复: 程序贴上来,大家一起研究下。

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

    作者回复: netty是Java的网络通信框架,其底层实现还是依赖类似epoll的事件分发机制的。

    spring mvc这类的使用的Java网络编程框架来做的,tomcat也是类似的。

    Nginx是使用类似epoll的机制来自己实现的。

    2019-09-13
收起评论
12
返回
顶部