19丨提高篇答疑:如何理解TCP四次挥手?
19丨提高篇答疑:如何理解TCP四次挥手?
讲述:冯永吉
时长11:16大小10.31M
如何理解 TCP 四次挥手?
最大分组 MSL 是 TCP 分组在网络中存活的最长时间吗?
关于 listen 函数中参数 backlog 的释义问题
UDP 连接和断开套接字的过程是怎样的?
在 UDP 中不进行 connect,为什么客户端会收到信息?
我们是否可以对一个 UDP 套接字进行多次 connect 的操作?
第 11 讲中程序和时序图的解惑
总结
赞 9
提建议
精选留言(28)
- 安排2019-09-13MSL的值怎么和TTL对应的啊?比如MSL设置为30秒,那怎么计算出TTL的值呢?怎么保证一个报文在网络中真的存活不超过30秒?
作者回复: TTL与MSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL。 设备在处理TTL的时候,是需要处理时间的,每次处理TTL时这个字段就都应该被减少,来反应花在处理报文上的时间。比如说处理了1秒减1,处理了2秒减2。这样就可以保证TTL为30的肯定活不过30秒。
共 9 条评论18 - Geek_f8c3792020-08-04signal(SIGPIPE, SIG_IGN); 实际上是忽略信号 而不是 按照默认的信号处理程序即退出
作者回复: 因为你给SIGPIPE信号设置了SIG_IGN,所以是忽略信号。我说的是如果没有设置,默认的SIGPIPE处理的方式即为退出。
5 - 钱2019-11-23MSL 是任何 IP 数据报能够在因特网中存活的最长时间。其实它的实现不是靠计时器来完成的,在每个数据报里都包含有一个被称为 TTL(time to live)的 8 位字段,它的最大值为 255。TTL 可译为“生存时间”,这个生存时间由源主机设置初始值,它表示的是一个 IP 数据报可以经过的最大跳跃数,每经过一个路由器,就相当于经过了一跳,它的值就减 1,当此值减为 0 时,则所在的路由器会将其丢弃,同时发送 ICMP 报文通知源主机 这是否意味着一个IP数据报不可能经过255个路由器? 请问一个IP数据报经过多少路由器,这个由谁决定?怎么决定?和网络距离距离有什么关系? 😅感觉老师的回答和问题,没有完全的对上?展开
作者回复: IP数据报经过多少路由器这个是无法确定的。
4 - 扩散性百万咸面包2020-04-22请问老师,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 报文得以自然消失,同时为了让被动关闭方能够正常关闭。
3 - 风羽星泉2019-09-17老师,我找到我提交的问题答案了。 使用 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 的值。
作者回复: 是的。
2 - 小蛋壳2019-09-13高性能的网络通信框架,是不是类似netty做的事?。那比如spring mvc或者其他任何应用程序框架其实底层都需要处理网络通讯这块。可以说知名的框架这块其实处理的都很好? java应用,是tomcat处理网络请求还是spring来处理的?还有nginx
作者回复: netty是Java的网络通信框架,其底层实现还是依赖类似epoll的事件分发机制的。 spring mvc这类的使用的Java网络编程框架来做的,tomcat也是类似的。 Nginx是使用类似epoll的机制来自己实现的。
2 - 铲铲队2022-04-23至于已完成连接队列,如果声明的 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值超过了最大值,则被截断为最大值把。展开
作者回复: 字面意思应该是你说的那种。
- 风羽星泉2019-09-17老师,我修改了程序中的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的值,如果比它大,则取内核设置的值。展开
作者回复: 因为你设置太大也没有,系统有个默认值。
共 2 条评论1 - 三年二班邱小东2022-02-25老师,为FIN包插入EOF的TCP协议栈是主动关闭方插入的,还是被动关闭方插入的?
作者回复: 主动方。
共 2 条评论 - GeekYanger2021-10-27记录一下,TIME_WAIT本身还是很有价值的,TIME_WAIT 的引入是为了让 TCP 报文得以自然消失,同时为了让被动关闭方能够正常关闭。
作者回复: 👍
- landing2021-10-17"注意服务器端程序,先通过 recvfrom 函数调用获取了客户端的地址和端口信息,这当然是可以的,因为 UDP 报文里面包含了这部分信息。"这里不理解。如果解释了客户端收到服务端的数据是因为服务端第一次接受客户端数据时获得了客户端的地址,然后通过sendto告诉了内核,那么第一步内核为什么把数据给服务端套接字,这一步没有建立映射关系,内核应该也不知道啊
作者回复: 内核收到数据是通过服务端套接字来完成的,而要把服务端的数据发送给客户端,需要绑定服务端套接字和客户端地址-端口,这就是通过代码中recvform和sendto来完成的。
- duckman2020-12-10突然发现了 无论是TCP/UDP, 建立连接之后, 服务端总是先read, 客户端总是先write。 所以,有了IO多路复用之后, 是不是 服务端/客户端可以抛弃这个经典的对话模式,完全根据业务层面的需求, 决定是先write还是先read, 而且两个动作是独立的,互不影响。展开
作者回复: 你的发现是我的程序例子的模板吧,实际上不一定是这样的。不过你对I/O多路复用的理解倒是有另外一个角度,也算是一个层面的理解吧。
- YUAN2020-10-03使用udp时,客户端如何知道服务器端收到了它发送的请求?例如dns查询,客户端发送的请求如果丢失,那么客户端如何知道发生了报文丢失?
作者回复: UDP就是不知道的, 使用的时候我们需要容忍这样的丢失。
- 宋菁2020-07-03老师好,udp没绑定端口的话,操作系统动态分配端口,有可能会出现两个socket自动绑定到同一个端口的情况吗
作者回复: 为啥会发生呢?系统自动选择端口,它应该会默默记下来使用过的端口的。
- pc2020-06-07看了前面的连接关闭、TCP对链路异常的感知,以及四次挥手,串起来后总感觉有点糊涂。看完这篇的几个问题,又稍微明白了一点。想着还是总结着提问一下: 1、首先ACK M+1 和 FIN N两次挥手不能合并吧?上学课本还有一些博客不是都有提到,两者之前被动关闭的一方还可以继续发送数据的。 2、所以TCP四次挥手简单总结为:A端发送FIN包、B端返回ACK;B端继续send data;B端发送FIN包、A端进入TIME_WAIT并发送ACK。 针对“被动关闭方继续send data”这点,回应到本文最后一个问题、以及TCP感知链路异常的几种情况———如果A端是close关闭,B端继续send data的时候就会收到RST、再write则触发SIGPIPE信号;如果A端是shutdown(1)关闭,才可以继续接收到B端的数据,B端也正常的继续send data。(就是文中最后的时序图) 这样的话,对于是不是可以理解成shutdown关闭的时候才是四次挥手的场景呢?反过来说,关闭的时候并不都是“标准的四次挥手”? 3、像kill -9这种暴力关闭程序,都应该类似close关闭吧?展开
作者回复: 1. 能不能合并我没有确切的答案,不过我觉得是可以优化的; 2.close和shutdown都是标准的四次挥手 3.我同意,不过这种是系统内核回收资源额外带来的结果。
共 2 条评论 - 林子2020-04-08针对UDP connect的问题有个疑问,按照上文说的是为了让内核记录目标ip端口到socket的映射关系,那如果源主机上有两个udp socket都connect同一个目标ip端口,这时如果出现icmp报文时内核是不是会通知这两个socket呢
作者回复: 好问题,我猜是不是会报错?
- awmthink2020-03-08老师,如果连接双方正好同时close conn fd,会怎么样呢,相当于FIN_WAIT_1时,收到了FIN,会不会直接跳过了FIN_WAIT_2,发送ACK后进入TIME_WAIT了呢。
作者回复: 这样的场景极其罕见,也很难模拟,而且TCP的状态其实是一个状态机驱动模式,肯定有一个先来后来的情况,进入先来的那个状态机驱动模式,就会按照那个模式走下去,而不是突然跳出来。
共 2 条评论 - 鸠摩·智2020-02-22老师,文章开头描述4次挥手,被动方读取数据到eof后,向主动方发fin的ack,主动方进入fin_wait_2,这里是不是缺失了?
作者回复: 确实是没有写,我加上,让编辑改下。
共 2 条评论 - 范闲2020-02-12四次挥手的ACKM+1 和 FIN N为啥不能合并到一起?
作者回复: 好问题,事实上为了节省带宽,确实有这样做的,这里为了讲述方便,将其分开。
共 3 条评论 - Douglas2020-01-09老师好像并没有讲为啥是4次挥手
作者回复: 理解挥手的目的就自然理解为啥是4此了,因为每个方向都需要一个 FIN 和一个 ACK,通常被称为四次挥手。