【问题标题】:Rejecting a TCP connection before it's being accepted?在接受 TCP 连接之前拒绝它?
【发布时间】:2009-11-17 22:11:20
【问题描述】:

winsock 中有 3 个不同的accept 版本。除了用于标准合规性的基本accept,还有似乎是最高级版本的AcceptEx(由于它的io 功能重叠)和WSAAccept。后者支持条件回调,据我所知,它允许在连接请求被接受之前拒绝连接请求(启用SO_CONDITIONAL_ACCEPT 选项时)。其他版本均不支持此功能。

由于我更喜欢​​使用 AcceptEx 和重叠 io,我想知道为什么这个功能只在更简单的版本中可用?

我对 TCP 的内部工作原理知之甚少,无法告诉我们在连接被接受之前拒绝连接和在连接建立后立即断开连接之间实际上有什么区别?如果有,有什么方法可以用AcceptEx 模仿WSAAccept 的功能?

有人能解释一下这个问题吗?

【问题讨论】:

    标签: tcp winsock


    【解决方案1】:

    当连接建立时,远端会发送一个设置了SYN标志的数据包。服务器回复SYN,ACK包,然后远端发送ACK包,其中可能已经包含数据。

    有两种方法可以中断 TCP 连接的形成。第一个是重置连接——这与连接到无人监听的端口时常见的“连接被拒绝”消息相同。在这种情况下,原始的 SYN 数据包会得到一个 RST 数据包的响应,该数据包会立即终止连接并且是无状态的。如果 SYN 被重新发送,RST 将从每个收到的 SYN 数据包中生成。

    第二个是在连接形成后立即关闭。在 TCP 级别上,无法立即关闭双向连接 - 你唯一能说的是“我不会再发送任何数据”。发生这种情况时,当初始 SYNSYN,ACKACK 交换完成时,服务器会发送 FIN 数据包到远端。在大多数情况下,用 FIN 告诉另一端“我不会再发送任何数据”会使另一端也关闭连接,并发送它自己的 FIN 数据包。以这种方式终止的连接与由于某种原因没有发送数据的正常连接没有任何不同。这意味着 TCP 连接的正常状态跟踪和延迟关闭状态将持续存在,就像正常连接一样。

    现在,在 C API 方面,这看起来有点不同。在端口上调用listen() 时,操作系统开始接受该端口上的连接。这意味着它开始向连接回复 SYN,ACK 数据包,无论 C 代码是否已调用 accept()。因此,在 TCP 方面,无论是在接受之前还是之后以某种方式关闭连接都没有区别。唯一额外的问题是侦听套接字有积压,这意味着它可以等待的未接受连接的数量,然后才开始对远程端说 RST

    但是,在 Windows 上,SO_CONDITIONAL_ACCEPT 调用允许应用程序控制积压队列。这意味着服务器不会对 SYN 数据包回答 anything,直到应用程序对连接进行某些操作。这意味着,在这个级别拒绝连接实际上可以在不创建状态的情况下向网络发送 RST 数据包。

    因此,如果您无法以某种方式在您使用AcceptEx 的套接字上启用SO_CONDITIONAL_ACCEPT 功能,则它将以不同的方式显示给网络。然而,真正使用即时 RST 功能的地方并不多,所以我认为对此的要求确实意味着一个非常专业的系统。对于最常见的用例,接受一个套接字然后关闭它是正常的行为方式。

    【讨论】:

      【解决方案2】:

      我无法评论 Windows 方面的事情,但就 TCP 而言,拒绝连接有点不同于断开连接 em> 来自它。

      一方面,断开连接意味着已经“消耗”了更多资源(例如,防火墙和端点中维护的端口状态,交换机/路由器中使用的转发容量等)网络和主机。 拒绝连接占用的资源较少。

      【讨论】:

        猜你喜欢
        • 2020-01-12
        • 2016-08-18
        • 1970-01-01
        • 2017-01-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-08
        • 2013-10-28
        相关资源
        最近更新 更多