在接受 TCP 连接之前拒绝它?

发布于 2024-08-12 00:14:19 字数 486 浏览 4 评论 0原文

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

由于我更喜欢​​将 AcceptEx 与重叠 io 一起使用,我想知道为什么此功能仅在更简单的版本中可用?

我对 TCP 的内部工作原理了解不够,无法判断在接受连接之前拒绝连接与在建立连接后立即断开套接字之间实际上有什么区别吗?如果有的话,有什么方法可以用 AcceptEx 来模仿 WSAAccept 功能吗?

有人可以阐明这个问题吗?

There are 3 different accept versions in winsock. Aside from the basic accept which is there for standard compliance, there's also AcceptEx which seems the most advanced version (due to it's overlapped io capabilities), and WSAAccept. The latter supports a condition callback, which as far as I understand, allows the rejection of connection requests before they're accepted (when the SO_CONDITIONAL_ACCEPT option is enabled). None of the other versions supports this functionality.

Since I prefer to use AcceptEx with overlapped io, I wonder how come this functionality is only available in the simpler version?

I don't know enough about the inner workings of TCP to tell wehter there's actually any difference between rejecting a connection before it has been accepted, and disconnecting a socket right after a connection has been established? And if there is, is there any way to mimic the WSAAccept functionality with AcceptEx?

Can someone shed some light over this issue?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

嘿看小鸭子会跑 2024-08-19 00:14:19

建立连接后,远程端会发送一个设置了 SYN 标志的数据包。服务器用SYN,ACK数据包进行应答,然后远程端发送ACK数据包,该数据包可能已经包含数据。

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

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

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

但是,在 Windows 上,SO_CONDITIONAL_ACCEPT 调用允许应用程序控制积压队列。这意味着,在应用程序对连接执行某些操作之前,服务器不会对 SYN 数据包做出任何响应。这意味着,在此级别拒绝连接实际上可以将RST数据包发送到网络而不创建状态。

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

When a connection is established, the remote end sends a packet with the SYN flag set. The server answers with a SYN,ACK packet, and after that the remote end sends an ACK packet, which may already contain data.

There are two ways to break a TCP connection from forming. The first is resetting the connection - this is the same as the common "connection refused" message seen when connecting to a port nobody is listening to. In this case, the original SYN packet is answered with a RST packet, which terminates the connection immediately and is stateless. If the SYN is resent, RST will be generated from every received SYN packet.

The second is closing the connection as soon as it has been formed. On the TCP level, there is no way to close the connection both ways immediately - the only thing you can say is that "I am not going to send any more data". This happens so that when the initial SYN, SYN,ACK, ACK exchange has finished, the server sends a FIN packet to the remote end. In most cases, telling the other end with FIN that "I am not going to send any more data" makes the other end close the connection as well, and send it's own FIN packet. A connection terminated this way isn't any different from a normal connection where no data was sent for some reason. This means that the normal state tracking for TCP connections and the lingering close states will persist, just like for normal connections.

Now, on the C API side, this looks a bit different. When calling listen() on a port, the OS starts accepting connections on that port. This means that is starts replying SYN,ACK packets to connections, regardless if the C code has called accept() yet. So, on the TCP side, it makes no difference whether the connection is somehow closed before or after accept. The only additional concern is that a listening socket has a backlog, which means the number of non-accepted connections it can have waiting, before it starts saying RST to the remote end.

However, on windows, the SO_CONDITIONAL_ACCEPT call allows the application to take control of the backlog queue. This means that the server will not answer anything to a SYN packet until the application does something with the connection. This means, that rejecting connections at this level can actually send RST packets to the network without creating state.

So, if you cannot get the SO_CONDITIONAL_ACCEPT functionality enabled somehow on the socket you are using AcceptEx on, it will show up differently to the network. However, not many places actually use the immediate RST functionality, so I would think the requirement for that must mean a very specialized system indeed. For most common use cases, accepting a socket and then closing it is the normal way to behave.

被翻牌 2024-08-19 00:14:19

我无法对 Windows 方面的事情发表评论,但就 TCP 而言,拒绝连接与断开连接有点不同它。

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

I can't comment on the Windows side of things but as far as TCP is concerned, rejecting a connection is a bit different than disconnecting from it.

For one, disconnecting from a connection means there were more resources already "consumed" (e.g. ports state maintained in Firewalls & end-points, forwarding capacity used in switches/routers etc.) in both the network and the hosts. Rejecting a connection is less resource intensive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文