关于 socket 的 shutdown close 函数的几个疑问?

2021-12-06 22:47:50 +08:00
 amiwrong123
  1. 调用 close 函数,并不会实际意义地马上执行 close (这是不是有点反常识了?),比如两个进程 共享一个 socket 的 fd ,那么第二个调用 close 的进程,才会马上 发送 FIN 包。

  2. 最后一个调用 close 的进程执行的动作 和 shutdown(SHUT_RDWR) 的唯一区别,就是 后者没有关闭描述符。

  3. 最后一个调用 close 的进程执行的动作 和 shutdown(SHUT_RDWR) 的相同点:都会马上发送一个 FIN 包,都会在应用程序层次上关闭读操作(这对应到第 5 点)。

  4. 最后一个调用 close 的进程执行的动作、调用 shutdown(SHUT_WR)、shutdown(SHUT_RDWR) ,都会 马上发送一个 FIN 包出去。

  5. 我理解是没有真正意义上的 shutdown(SHUT_RD),因为你无法阻止对方传数据过来,所以 shutdown(SHUT_RD)只是 象征性 关闭了读,内核其实还在接受数据,只是内核会直接丢弃掉数据,不让应用程序有机会读到。

  6. 基于上一点,如果我调用了 shutdown(SHUT_RD),内核会把对方发来的普通数据都给丢弃掉,即使对方一直会源源不断地一直发数据过来。但如果是 对方发来的是一个 FIN 包呢,此时 内核会 返回一个 对应的 ACK 包回去吗?

大佬们,看看我这些理解对吗,望指点一下

918 次点击
所在节点    程序员
6 条回复
anytk
2021-12-07 10:36:38 +08:00
FIN 包是 tcp 协议的要求,tcp 连接断开有 4 次包交互;
socket 只是操作系统抽象出来管理的,多进程共享 socket 是常见的,比如 fork 的子进程会共享复制父进程的 socket ,但实际上都只是引用计数到同一个对象上;
试着把 tcp 协议握手部分跟 bsd socket 实现先分开理解。
julyclyde
2021-12-07 13:07:19 +08:00
1 并没有反常识啊。close 是针对 fd 的操作
amiwrong123
2021-12-07 14:07:21 +08:00
@anytk #1
@julyclyde #2
大佬,能不能看下第 2 点,第 5 第 6 点,我很纠结这几个。感谢
julyclyde
2021-12-07 14:36:37 +08:00
@amiwrong123 感觉研究这个意义不大啊。交给底层自动处理就行吧?
anytk
2021-12-07 15:01:08 +08:00
@amiwrong123
#2 就跟楼上说的一样,close 是针对 fd 资源的,以及必要的其他操作,如果 socket 没有调用过 shutdown ,那么 close 调用的同时也会调用操作。shutdown 是针对 tcp 协议的操作,因为某些应用可能要使用独特的协议特征,那么这里不同操作的接口就更加简便。

#5 可以这么理解,都是内核的 tcp 栈在处理,不暴露给应用层
#6 按照 tcp 断开的逻辑,如果对端遵从协议就按照协议交互发包,如果出现意外,得看内核如何处理来保证安全,不然就会被 ddos
amiwrong123
2021-12-07 15:10:16 +08:00
@anytk #5
> close 是针对 fd 资源的,shutdown 是针对 tcp 协议的操作。

那我理解,调用 close 后(假设只有一个进程共享了 fd ),就不需要再调用 shutdown(SHUT_RDWR)
但,调用 shutdown(SHUT_RDWR) 后,还需要再调用 close 呗

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/820482

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX