【问题标题】:Why will a TCP Server send a FIN immediately after accepting a connection?为什么 TCP Server 接受连接后会立即发送 FIN?
【发布时间】:2011-04-21 16:18:54
【问题描述】:

从 ethreal 数据包捕获中,我看到以下对我来说似乎很奇怪的行为:

Client --> Server  [SYN]
Server --> Client  [SYN, ACK]
Client --> Server  [ACK]
Server --> Client  [FIN, ACK]
Client --> Server  [ACK]
Client --> Server  [TCP Segment of a reassembled PDU] (I don't know what this means)
Server --> Client  [RST]

关于为什么会发生这种情况的任何想法?

另外,服务器端口是 6000。这会导致什么问题吗?

我的其他疑问:

  1. 为什么会有 FIN、ACK?不应该只有FIN吗?该消息中的 ACK 是什么意思?
  2. 不应该有来自客户端的 FIN 吗?

编辑: 经过进一步分析,我发现如果文件描述符的数量超过了限制,那么服务器会发送一个 FIN。但是,在这种情况下,文件描述符似乎没有超过限制。还有哪些情况会发生这种情况?

【问题讨论】:

标签: tcp


【解决方案1】:

经过深入分析,发现问题原因如下:

当客户端尝试 TCP 连接时,即使服务器当前没有调用接受,连接也会通过。如果服务器调用了“侦听”功能,就会发生这种情况,并且它将继续接受连接,直到达到积压限制。

但是,如果应用程序进程超过了它可以使用的最大文件描述符的限制,那么当服务器调用accept时,它就会意识到没有文件描述符可以分配给socket,并且accept调用和TCP失败向另一端发送 FIN 的连接。

我只是想在这里发布这个发现。我仍然将接受的答案保留为哈比的答案。

感谢所有回答这个问题的人。

【讨论】:

    【解决方案2】:

    FIN 通常表示套接字上名为shutdown(..) 的另一端。

    【讨论】:

    • 你的意思是说,在这种情况下,对 'accept' 的调用肯定会成功返回?
    • 是的。如果没有 accept(),您只会看到静默并最终超时。
    • 好的,但是,accept 不可能发送 FIN 对吧?我的意思是如果出现一些错误情况,有可能吗?
    • 我不知道,当然。
    • 嗯?不,连接是在调用 accept() 之前建立的 - listen() 的 backlog 参数指定了可以处于此状态的连接数(已连接,但尚未调用 accept())。
    【解决方案3】:

    我猜想inetd 或类似的守护进程正在接受连接,然后它会尝试forkexec 另一个程序来处理连接,并且fork 失败(由于资源耗尽)或exec 失败(由于文件不存在、权限错误等)。

    【讨论】:

      【解决方案4】:

      可能是TCP wrappers。如果服务器进程是使用 libwrap 支持构建的,它将接受连接,检查/etc/hosts.allow/etc/hosts.deny,如果被策略拒绝,则立即关闭连接。

      很容易看出服务器是否在使用 libwrap:

      > ldd /usr/sbin/sshd | grep libwrap
      libwrap.so.0 => /lib64/libwrap.so.0 (0x00007f1562d44000)
      

      【讨论】:

        【解决方案5】:

        我认为 FIN 是通过调用 close() 而不是 shutdown() 发送的。

        连接在积压队列中;在 accept() 之后,服务器决定以任何原因终止它(例如 TCP 包装 ACL 或文件描述符不足)。在这种情况下,close() 将文件描述符 (FD) 的链接计数从 1 减少到 0,因此该连接的 FD 被完全销毁。之后,从服务器的角度来看,客户端将数据发送到一个不存在的套接字,服务器必须响应一个 RST。

        如果是shutdown(),服务器仍然可以恢复客户端发送的数据,并且必须等待客户端的FIN才能优雅地关闭连接。没有 RST 被发回。

        附言 close() vs shutdown()

        【讨论】:

          【解决方案6】:

          似乎服务器在接受连接后不久就调用了shutdown

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2013-08-11
            • 1970-01-01
            • 1970-01-01
            • 2016-08-20
            • 1970-01-01
            • 1970-01-01
            • 2012-10-14
            相关资源
            最近更新 更多