在 TCP 连接被接受之前拒绝它? [英] Rejecting a TCP connection before it's being accepted?

查看:31
本文介绍了在 TCP 连接被接受之前拒绝它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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.

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

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

我对 TCP 的内部工作原理知之甚少,无法说明在连接被接受之前拒绝连接与在连接建立后立即断开套接字之间实际上有什么区别?如果有的话,有没有办法用 AcceptEx 来模仿 WSAAccept 的功能?

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?

推荐答案

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

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.

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

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.

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

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.

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

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.

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

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.

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

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.

这篇关于在 TCP 连接被接受之前拒绝它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆