V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
amiwrong123
V2EX  ›  程序员

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

  •  
  •   amiwrong123 · 2021-12-06 22:47:50 +08:00 · 1021 次点击
    这是一个创建于 1116 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 包回去吗?

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

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

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

    那我理解,调用 close 后(假设只有一个进程共享了 fd ),就不需要再调用 shutdown(SHUT_RDWR)
    但,调用 shutdown(SHUT_RDWR) 后,还需要再调用 close 呗
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5823 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 35ms · UTC 06:22 · PVG 14:22 · LAX 22:22 · JFK 01:22
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.