在接受之前拒绝TCP连接?

时间:2009-11-17 22:11:20

标签: tcp winsock

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

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

我不太了解TCP的内部工作原理,告诉我们在接受连接之前拒绝连接与在连接建立后断开套接字之间实际上有什么区别?如果有,是否有办法模仿WSAAccept的{​​{1}}功能?

有人可以对这个问题有所了解吗?

2 个答案:

答案 0 :(得分:17)

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

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

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

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

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

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

答案 1 :(得分:1)

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

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