调用 close 函数,并不会实际意义地马上执行 close (这是不是有点反常识了?),比如两个进程 共享一个 socket 的 fd ,那么第二个调用 close 的进程,才会马上 发送 FIN 包。
最后一个调用 close 的进程执行的动作 和 shutdown(SHUT_RDWR) 的唯一区别,就是 后者没有关闭描述符。
最后一个调用 close 的进程执行的动作 和 shutdown(SHUT_RDWR) 的相同点:都会马上发送一个 FIN 包,都会在应用程序层次上关闭读操作(这对应到第 5 点)。
最后一个调用 close 的进程执行的动作、调用 shutdown(SHUT_WR)、shutdown(SHUT_RDWR) ,都会 马上发送一个 FIN 包出去。
我理解是没有真正意义上的 shutdown(SHUT_RD),因为你无法阻止对方传数据过来,所以 shutdown(SHUT_RD)只是 象征性 关闭了读,内核其实还在接受数据,只是内核会直接丢弃掉数据,不让应用程序有机会读到。
基于上一点,如果我调用了 shutdown(SHUT_RD),内核会把对方发来的普通数据都给丢弃掉,即使对方一直会源源不断地一直发数据过来。但如果是 对方发来的是一个 FIN 包呢,此时 内核会 返回一个 对应的 ACK 包回去吗?
大佬们,看看我这些理解对吗,望指点一下
1
anytk 2021-12-07 10:36:38 +08:00
FIN 包是 tcp 协议的要求,tcp 连接断开有 4 次包交互;
socket 只是操作系统抽象出来管理的,多进程共享 socket 是常见的,比如 fork 的子进程会共享复制父进程的 socket ,但实际上都只是引用计数到同一个对象上; 试着把 tcp 协议握手部分跟 bsd socket 实现先分开理解。 |
2
julyclyde 2021-12-07 13:07:19 +08:00
1 并没有反常识啊。close 是针对 fd 的操作
|
3
amiwrong123 OP |
4
julyclyde 2021-12-07 14:36:37 +08:00
@amiwrong123 感觉研究这个意义不大啊。交给底层自动处理就行吧?
|
5
anytk 2021-12-07 15:01:08 +08:00
@amiwrong123
#2 就跟楼上说的一样,close 是针对 fd 资源的,以及必要的其他操作,如果 socket 没有调用过 shutdown ,那么 close 调用的同时也会调用操作。shutdown 是针对 tcp 协议的操作,因为某些应用可能要使用独特的协议特征,那么这里不同操作的接口就更加简便。 #5 可以这么理解,都是内核的 tcp 栈在处理,不暴露给应用层 #6 按照 tcp 断开的逻辑,如果对端遵从协议就按照协议交互发包,如果出现意外,得看内核如何处理来保证安全,不然就会被 ddos |
6
amiwrong123 OP @anytk #5
> close 是针对 fd 资源的,shutdown 是针对 tcp 协议的操作。 那我理解,调用 close 后(假设只有一个进程共享了 fd ),就不需要再调用 shutdown(SHUT_RDWR) 但,调用 shutdown(SHUT_RDWR) 后,还需要再调用 close 呗 |